diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..287f57a --- /dev/null +++ b/.clang-format @@ -0,0 +1,200 @@ +--- +Language: Cpp +# BasedOnStyle: Google +AccessModifierOffset: -1 +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: None +AlignConsecutiveAssignments: None +AlignConsecutiveBitFields: None +AlignConsecutiveDeclarations: None +AlignEscapedNewlines: Left +AlignOperands: Align +AlignTrailingComments: true +AllowAllArgumentsOnNextLine: true +AllowAllConstructorInitializersOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortEnumsOnASingleLine: true +AllowShortBlocksOnASingleLine: Never +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: All +AllowShortLambdasOnASingleLine: All +AllowShortIfStatementsOnASingleLine: WithoutElse +AllowShortLoopsOnASingleLine: true +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: true +AlwaysBreakTemplateDeclarations: Yes +AttributeMacros: + - __capability +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterCaseLabel: true + AfterClass: false + AfterControlStatement: Always + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: true +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakInheritanceList: BeforeColon +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DeriveLineEnding: true +DerivePointerAlignment: true +DisableFormat: false +EmptyLineBeforeAccessModifier: LogicalBlock +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +StatementAttributeLikeMacros: + - Q_EMIT +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*\.h>' + Priority: 1 + SortPriority: 0 + CaseSensitive: false + - Regex: '^<.*' + Priority: 2 + SortPriority: 0 + CaseSensitive: false + - Regex: '.*' + Priority: 3 + SortPriority: 0 + CaseSensitive: false +IncludeIsMainRegex: '([-_](test|unittest))?$' +IncludeIsMainSourceRegex: '' +IndentCaseLabels: true +IndentCaseBlocks: false +IndentGotoLabels: true +IndentPPDirectives: None +IndentExternBlock: AfterExternBlock +IndentRequires: false +IndentWidth: 4 +IndentWrappedFunctionNames: false +InsertTrailingCommas: None +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: false +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBinPackProtocolList: Never +ObjCBlockIndentWidth: 2 +ObjCBreakBeforeNestedBlockParam: true +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 1 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyBreakTemplateDeclaration: 10 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PenaltyIndentedWhitespace: 0 +PointerAlignment: Right +RawStringFormats: + - Language: Cpp + Delimiters: + - cc + - CC + - cpp + - Cpp + - CPP + - 'c++' + - 'C++' + CanonicalDelimiter: '' + BasedOnStyle: google + - Language: TextProto + Delimiters: + - pb + - PB + - proto + - PROTO + EnclosingFunctions: + - EqualsProto + - EquivToProto + - PARSE_PARTIAL_TEXT_PROTO + - PARSE_TEST_PROTO + - PARSE_TEXT_PROTO + - ParseTextOrDie + - ParseTextProtoOrDie + - ParseTestProto + - ParsePartialTestProto + CanonicalDelimiter: '' + BasedOnStyle: google +ReflowComments: true +SortIncludes: false +SortJavaStaticImport: Before +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterLogicalNot: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeCaseColon: false +SpaceBeforeCpp11BracedList: false +SpaceBeforeCtorInitializerColon: true +SpaceBeforeInheritanceColon: true +SpaceBeforeParens: Never +SpaceAroundPointerQualifiers: Default +SpaceBeforeRangeBasedForLoopColon: true +SpaceInEmptyBlock: false +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 2 +SpacesInAngles: false +SpacesInConditionalStatement: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +SpaceBeforeSquareBrackets: false +BitFieldColonSpacing: Both +Standard: Auto +StatementMacros: + - Q_UNUSED + - QT_REQUIRE_VERSION +TabWidth: 4 +UseCRLF: false +UseTab: Never +WhitespaceSensitiveMacros: + - STRINGIZE + - PP_STRINGIZE + - BOOST_PP_STRINGIZE + - NS_SWIFT_NAME + - CF_SWIFT_NAME +... + diff --git a/Android.bp b/Android.bp index e9efbe5..fdd3ec2 100644 --- a/Android.bp +++ b/Android.bp @@ -24,6 +24,17 @@ cc_library_headers { min_sdk_version: "29", } +cc_library_headers { + name: "libmvcdec_headers", + export_include_dirs: [ + "decoder", + "decoder/mvc", + "common", + "common/mvc", + ], + min_sdk_version: "29", +} + cc_library_headers { name: "libavcenc_headers", export_include_dirs: [ @@ -33,15 +44,8 @@ cc_library_headers { min_sdk_version: "29", } -cc_library_static { - name: "libavcdec", - vendor_available: true, - host_supported: true, - shared_libs: [ - "liblog", - "libcutils", - ], - +cc_defaults { + name: "libavc_mvc_dec_defaults", cflags: [ "-fPIC", "-O3", @@ -52,6 +56,87 @@ cc_library_static { // #KEEP_THREAD_ACTIVE is experimental "-UKEEP_THREADS_ACTIVE", ], + vendor_available: true, + host_supported: true, + shared_libs: [ + "liblog", + "libcutils", + ], + + arch: { + arm: { + local_include_dirs: [ + "decoder/arm", + "common/arm", + ], + cflags: [ + "-DARM", + // These will be overriden by armv7_a_neon + "-DDISABLE_NEON", + "-DDEFAULT_ARCH=D_ARCH_ARM_NONEON", + ], + + neon: { + cflags: [ + "-UDISABLE_NEON", + "-UDEFAULT_ARCH", + "-DDEFAULT_ARCH=D_ARCH_ARM_A9Q", + ], + }, + }, + + arm64: { + cflags: [ + "-DARMV8", + "-DARM", + "-DDEFAULT_ARCH=D_ARCH_ARMV8_GENERIC", + ], + local_include_dirs: [ + "decoder/arm", + "common/armv8", + ], + }, + + x86: { + cflags: [ + "-DX86", + "-msse4.2", + "-DDEFAULT_ARCH=D_ARCH_X86_SSE42", + ], + + local_include_dirs: [ + "decoder/x86", + "common/x86", + ], + }, + + x86_64: { + cflags: [ + "-DX86", + "-msse4.2", + "-DDEFAULT_ARCH=D_ARCH_X86_SSE42", + ], + + local_include_dirs: [ + "decoder/x86", + "common/x86", + ], + }, + }, + + sanitize: { + integer_overflow: true, + misc_undefined: ["bounds"], + cfi: true, + config: { + cfi_assembly_support: true, + }, + }, +} + +cc_library_static { + name: "libavcdec", + defaults: ["libavc_mvc_dec_defaults"], export_include_dirs: [ "common", @@ -106,24 +191,11 @@ cc_library_static { arch: { arm: { - local_include_dirs: [ - "decoder/arm", - "common/arm", - ], - srcs: [ "decoder/arm/ih264d_function_selector.c", "common/arm/ih264_arm_memory_barrier.s", ], - cflags: [ - "-DARM", - - // These will be overriden by armv7_a_neon - "-DDISABLE_NEON", - "-DDEFAULT_ARCH=D_ARCH_ARM_NONEON", - ], - neon: { srcs: [ "decoder/arm/ih264d_function_selector_a9q.c", @@ -151,25 +223,10 @@ cc_library_static { "common/arm/ih264_iquant_itrans_recon_dc_a9.s", "common/arm/ih264_ihadamard_scaling_a9.s", ], - cflags: [ - "-UDISABLE_NEON", - "-UDEFAULT_ARCH", - "-DDEFAULT_ARCH=D_ARCH_ARM_A9Q", - ], }, }, arm64: { - cflags: [ - "-DARMV8", - "-DARM", - "-DDEFAULT_ARCH=D_ARCH_ARMV8_GENERIC", - ], - local_include_dirs: [ - "decoder/arm", - "common/armv8", - ], - srcs: [ "decoder/arm/ih264d_function_selector.c", "decoder/arm/ih264d_function_selector_av8.c", @@ -200,17 +257,6 @@ cc_library_static { }, x86: { - cflags: [ - "-DX86", - "-msse4.2", - "-DDEFAULT_ARCH=D_ARCH_X86_SSE42", - ], - - local_include_dirs: [ - "decoder/x86", - "common/x86", - ], - srcs: [ "decoder/x86/ih264d_function_selector.c", "decoder/x86/ih264d_function_selector_sse42.c", @@ -231,17 +277,6 @@ cc_library_static { }, x86_64: { - cflags: [ - "-DX86", - "-msse4.2", - "-DDEFAULT_ARCH=D_ARCH_X86_SSE42", - ], - - local_include_dirs: [ - "decoder/x86", - "common/x86", - ], - srcs: [ "decoder/x86/ih264d_function_selector.c", "decoder/x86/ih264d_function_selector_sse42.c", @@ -263,12 +298,6 @@ cc_library_static { }, sanitize: { - integer_overflow: true, - misc_undefined: ["bounds"], - cfi: true, - config: { - cfi_assembly_support: true, - }, blocklist: "libavc_blocklist.txt", }, apex_available: [ @@ -278,6 +307,31 @@ cc_library_static { min_sdk_version: "29", } +cc_library_static { + name: "libmvcdec", + defaults: ["libavc_mvc_dec_defaults"], + whole_static_libs: [ + "libavcdec", + ], + + export_include_dirs: [ + "decoder", + "decoder/mvc", + "common", + "common/mvc", + ], + + srcs: [ + "decoder/mvc/imvcd_api.c", + "decoder/mvc/imvcd_api_utils.c", + "decoder/mvc/imvcd_dpb_manager.c", + "decoder/mvc/imvcd_error_handler.c", + "decoder/mvc/imvcd_nalu_parser.c", + "decoder/mvc/imvcd_slice_functions.c", + "decoder/mvc/imvcd_utils.c", + ], +} + cc_library_static { name: "libavcenc", vendor_available: true, diff --git a/CMakeLists.txt b/CMakeLists.txt index 6caee5c..75fa4d4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,10 +36,13 @@ libavc_set_link_libraries() include("${AVC_ROOT}/common/common.cmake") include("${AVC_ROOT}/decoder/libavcdec.cmake") +include("${AVC_ROOT}/decoder/mvc/libmvcdec.cmake") include("${AVC_ROOT}/encoder/libavcenc.cmake") include("${AVC_ROOT}/test/decoder/avcdec.cmake") +include("${AVC_ROOT}/test/mvcdec/mvcdec.cmake") include("${AVC_ROOT}/test/encoder/avcenc.cmake") include("${AVC_ROOT}/fuzzer/avc_dec_fuzzer.cmake") +include("${AVC_ROOT}/fuzzer/mvc_dec_fuzzer.cmake") include("${AVC_ROOT}/fuzzer/avc_enc_fuzzer.cmake") diff --git a/common/common.cmake b/common/common.cmake index a8e599b..47ca54b 100644 --- a/common/common.cmake +++ b/common/common.cmake @@ -24,6 +24,7 @@ list( "${AVC_ROOT}/common/ithread.c") include_directories(${AVC_ROOT}/common) +include_directories(${AVC_ROOT}/common/mvc) # arm/x86 sources if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64") diff --git a/common/ih264_debug.h b/common/ih264_debug.h index 96ff2a7..63d5c71 100644 --- a/common/ih264_debug.h +++ b/common/ih264_debug.h @@ -38,6 +38,7 @@ #ifndef _IH264_DEBUG_H_ #define _IH264_DEBUG_H_ +#include #if DEBUG_PRINT diff --git a/common/mvc/imvc_defs.h b/common/mvc/imvc_defs.h new file mode 100644 index 0000000..c7e0705 --- /dev/null +++ b/common/mvc/imvc_defs.h @@ -0,0 +1,114 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#ifndef _IMVC_DEFS_H_ +#define _IMVC_DEFS_H_ + +#define MAX_NUM_VIEWS 6 + +#define LOG2_MAX_NUM_VIEWS 3 + +#define MAX_NUM_IVP_REFS MAX_NUM_VIEWS + +#define MAX_NUM_LEVEL_VALUES_SIGNALLED 1 + +#define MAX_NUM_OPERATING_POINTS 1 + +#define MULTIVIEW_HIGH_PROFILE_IDC 118 + +#define NUM_OF_ZERO_BYTES_BEFORE_START_CODE 2 + +#define EMULATION_PREVENTION_BYTE 0x03 + +#define MIN_H264_QP 0 + +#define MAX_H264_QP 51 + +#define NUM_SP_COMPONENTS 2 + +#define NUM_COMPONENTS 3 + +#define FORCEINLINE __attribute__((always_inline)) inline + +typedef void *FT_ALIGNED_ALLOC(void *pv_mem_ctxt, WORD32 i4_alignment, WORD32 i4_size); + +typedef void FT_ALIGNED_FREE(void *pv_mem_ctxt, void *pv_buf); + +typedef enum COMPONENT_TYPES_T +{ + Y = 0, + UV = 1, + U = 1, + V = 2, +} COMPONENT_TYPES_T; + +typedef enum AVC_EXT_NALU_ID_T +{ + UNSPEC_0 = 0, + + SLICE_NON_IDR = 1, + + SLICE_DPA = 2, + + SLICE_DPB = 3, + + SLICE_DPC = 4, + + SLICE_IDR = 5, + + SEI = 6, + + SPS = 7, + + PPS = 8, + + AUD = 9, + + EOSEQ = 10, + + EOSTR = 11, + + FILLER = 12, + + SPSE = 13, + + PREFIX_NAL = 14, + + SUBSET_SPS = 15, + + AUX_PIC = 19, + + CODED_SLICE_EXTENSION = 20, + + UNSPEC_31 = 24 + +} AVC_EXT_NALU_ID_T; + +typedef enum SLICE_TYPES_T +{ + PSLICE = 0, + BSLICE = 1, + ISLICE = 2, + SPSLICE = 3, + SISLICE = 4, + MAXSLICE_TYPE, +} SLICE_TYPES_T; + +#endif diff --git a/common/mvc/imvc_structs.h b/common/mvc/imvc_structs.h new file mode 100644 index 0000000..faf3ff9 --- /dev/null +++ b/common/mvc/imvc_structs.h @@ -0,0 +1,164 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#ifndef _IMVC_STRUCTS_H_ +#define _IMVC_STRUCTS_H_ + +#include "ih264_typedefs.h" +#include "imvc_defs.h" + +typedef struct nalu_mvc_ext_t +{ + UWORD8 u1_non_idr_flag; + + UWORD8 u1_priority_id; + + UWORD16 u2_view_id; + + UWORD8 u1_temporal_id; + + UWORD8 u1_anchor_pic_flag; + + UWORD8 u1_inter_view_flag; + +} nalu_mvc_ext_t; + +typedef struct mvc_ivp_ref_data_t +{ + UWORD8 u1_num_refs; + + UWORD16 au2_ref_view_ids[MAX_NUM_IVP_REFS]; + +} mvc_ivp_ref_data_t; + +typedef struct mvc_op_data_t +{ + UWORD8 u1_temporal_id; + + UWORD16 u2_num_ops; + + UWORD16 u2_num_target_views; + + UWORD16 au2_target_view_ids[MAX_NUM_VIEWS]; + + /* Counter for num target views and views each target is dependent on */ + UWORD16 u2_num_views; + +} mvc_op_data_t; + +typedef struct mvc_level_info_t +{ + UWORD32 u4_level_idc; + + mvc_op_data_t as_mvc_op_data[MAX_NUM_OPERATING_POINTS]; + +} mvc_level_info_t; + +typedef struct sps_mvc_ext_t +{ + UWORD16 u2_num_views; + + UWORD16 au2_view_ids[MAX_NUM_VIEWS]; + + /* 0 => L0; 1 => L1 */ + mvc_ivp_ref_data_t as_anchor_ref_data[2][MAX_NUM_VIEWS]; + + /* 0 => L0; 1 => L1 */ + mvc_ivp_ref_data_t as_non_anchor_ref_data[2][MAX_NUM_VIEWS]; + + UWORD8 u1_num_level_values_signalled; + + mvc_level_info_t as_mvc_level_info[MAX_NUM_LEVEL_VALUES_SIGNALLED]; + +} sps_mvc_ext_t; + +typedef struct mvc_vui_ext_t +{ + UWORD16 u2_vui_mvc_num_ops; + + UWORD8 u1_vui_mvc_temporal_id[MAX_NUM_OPERATING_POINTS]; + + UWORD16 u2_vui_mvc_num_target_output_views[MAX_NUM_OPERATING_POINTS]; + + UWORD16 u2_vui_mvc_view_id[MAX_NUM_OPERATING_POINTS][MAX_NUM_VIEWS]; + + UWORD8 u1_vui_mvc_timing_info_present_flag[MAX_NUM_OPERATING_POINTS]; + + UWORD32 u4_vui_mvc_num_units_in_tick[MAX_NUM_OPERATING_POINTS]; + + UWORD32 u4_vui_mvc_time_scale[MAX_NUM_OPERATING_POINTS]; + + UWORD8 u1_vui_mvc_fixed_frame_rate_flag[MAX_NUM_OPERATING_POINTS]; + + UWORD8 u1_vui_mvc_nal_hrd_parameters_present_flag[MAX_NUM_OPERATING_POINTS]; + + UWORD8 u1_vui_mvc_vcl_hrd_parameters_present_flag[MAX_NUM_OPERATING_POINTS]; + + UWORD8 u1_vui_mvc_low_delay_hrd_flag[MAX_NUM_OPERATING_POINTS]; + + UWORD8 u1_vui_mvc_pic_struct_present_flag[MAX_NUM_OPERATING_POINTS]; + +} mvc_vui_ext_t; + +typedef struct buffer_container_t +{ + void *pv_data; + + WORD32 i4_data_stride; + +} buffer_container_t; + +typedef struct yuv_buf_props_t +{ + buffer_container_t as_component_bufs[NUM_COMPONENTS]; + + UWORD8 u1_bit_depth; + + UWORD16 u2_width; + + UWORD16 u2_height; + +} yuv_buf_props_t; + +typedef struct iv_mvc_yuv_buf_t +{ + yuv_buf_props_t as_view_buf_props[MAX_NUM_VIEWS]; + +} iv_mvc_yuv_buf_t; + +typedef struct coordinates_t +{ + WORD32 i4_abscissa; + + WORD32 i4_ordinate; +} coordinates_t; + +typedef struct offsets_t +{ + UWORD16 u2_top_offset; + + UWORD16 u2_bottom_offset; + + UWORD16 u2_left_offset; + + UWORD16 u2_right_offset; +} offsets_t; + +#endif diff --git a/decoder/ih264d_api_utils.h b/decoder/ih264d_api_utils.h new file mode 100644 index 0000000..61e474c --- /dev/null +++ b/decoder/ih264d_api_utils.h @@ -0,0 +1,72 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : ih264d_api_utils.h */ +/* */ +/* Description : This file contains function prototypes for non-API */ +/* functions defined in ih264d_api.c */ +/*****************************************************************************/ + +#ifndef _IH264D_API_UTILS_H_ +#define _IH264D_API_UTILS_H_ + +#include "ih264_typedefs.h" +#include "iv.h" + +#define MIN_IN_BUFS 1 +#define MIN_OUT_BUFS_420 3 +#define MIN_OUT_BUFS_422ILE 1 +#define MIN_OUT_BUFS_RGB565 1 +#define MIN_OUT_BUFS_420SP 2 + +extern WORD32 ih264d_create(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_delete(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_video_decode(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_set_params(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_set_num_cores(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_set_processor(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_set_degrade(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_set_flush_mode(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern WORD32 ih264d_get_buf_info(iv_obj_t *dec_hdl, void *pv_api_ip, void *pv_api_op); + +extern UWORD32 ih264d_get_outbuf_size(WORD32 u4_pic_wd, UWORD32 u4_pic_ht, UWORD8 u1_chroma_format, + UWORD32 *pu4_buf_size); + +extern void ih264d_export_sei_params(ivd_sei_decode_op_t *ps_sei_decode_op, dec_struct_t *ps_dec); + +extern UWORD32 ih264d_map_error(UWORD32 i4_err_status); + +extern void ih264d_signal_decode_thread(dec_struct_t *ps_dec); + +extern void ih264d_signal_bs_deblk_thread(dec_struct_t *ps_dec); + +extern WORD32 ih264d_deblock_display(dec_struct_t *ps_dec); + +#endif diff --git a/decoder/mvc/imvcd.h b/decoder/mvc/imvcd.h new file mode 100644 index 0000000..0160e17 --- /dev/null +++ b/decoder/mvc/imvcd.h @@ -0,0 +1,279 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ +/** +******************************************************************************* +* @file +* imvcd.h +* +* @brief +* This file contains all the necessary structure and enumeration +* definitions needed for the Application Program Interface(API) of the +* Ittiam MVC Decoder +* +******************************************************************************* +*/ + +#ifndef _IMVCD_H_ +#define _IMVCD_H_ +#include + +#include "ih264_typedefs.h" +#include "iv.h" +#include "ivd.h" + +/* Extern functions */ +extern IV_API_CALL_STATUS_T imvcd_api_function(iv_obj_t *ps_dec_hdl, void *pv_ip, void *pv_op); + +/* Typedefs */ +typedef enum IMVCD_CTL_SUB_CMDS +{ + IMVCD_CTL_SET_NUM_CORES = IVD_CMD_CTL_CODEC_SUBCMD_START, + IMVCD_CTL_SET_PROCESSOR = IVD_CMD_CTL_CODEC_SUBCMD_START + 1, + IMVCD_CTL_GET_VUI_PARAMS = IVD_CMD_CTL_CODEC_SUBCMD_START + 2, + IMVCD_CTL_DEGRADE = IVD_CMD_CTL_CODEC_SUBCMD_START + 3, + +} IMVCD_CTL_SUB_CMDS; + +typedef struct imvcd_create_ip_t +{ + ivd_create_ip_t s_ivd_ip; + +} imvcd_create_ip_t; + +typedef struct imvcd_create_op_t +{ + ivd_create_op_t s_ivd_op; + +} imvcd_create_op_t; + +typedef struct imvcd_delete_ip_t +{ + ivd_delete_ip_t s_ivd_ip; + +} imvcd_delete_ip_t; + +typedef struct imvcd_delete_op_t +{ + ivd_delete_op_t s_ivd_op; + +} imvcd_delete_op_t; + +typedef struct imvcd_video_decode_ip_t +{ + ivd_video_decode_ip_t s_ivd_ip; + +} imvcd_video_decode_ip_t; + +typedef struct imvcd_video_decode_op_t +{ + ivd_video_decode_op_t s_ivd_op; + + iv_yuv_buf_t *ps_view_disp_bufs; + +} imvcd_video_decode_op_t; + +typedef struct imvcd_set_config_ip_t +{ + ivd_ctl_set_config_ip_t s_ivd_ip; +} imvcd_set_config_ip_t; + +typedef struct imvcd_set_config_op_t +{ + ivd_ctl_set_config_op_t s_ivd_op; +} imvcd_set_config_op_t; + +typedef struct imvcd_set_num_cores_ip_t +{ + UWORD32 u4_size; + + IVD_API_COMMAND_TYPE_T e_cmd; + + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + + UWORD32 u4_num_cores; +} imvcd_set_num_cores_ip_t; + +typedef struct imvcd_set_num_cores_op_t +{ + UWORD32 u4_size; + + UWORD32 u4_error_code; +} imvcd_set_num_cores_op_t; + +typedef struct imvcd_set_arch_ip_t +{ + UWORD32 u4_size; + + IVD_API_COMMAND_TYPE_T e_cmd; + + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + + IVD_ARCH_T e_arch; + + IVD_SOC_T e_soc; + +} imvcd_set_arch_ip_t; + +typedef struct imvcd_set_arch_op_t +{ + UWORD32 u4_size; + + UWORD32 u4_error_code; +} imvcd_set_arch_op_t; + +typedef struct imvcd_set_degrade_mode_ip_t +{ + UWORD32 u4_size; + + IVD_API_COMMAND_TYPE_T e_cmd; + + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + + /** + * Pictures that are are degraded + * 0 : No degrade + * 1 : Only on non-reference frames + * 2 : Use interval specified by u4_nondegrade_interval + * 3 : All non-key frames + * 4 : All frames + */ + WORD32 i4_degrade_pics; + + /** + * Interval for pictures which are completely decoded without any degradation + */ + WORD32 i4_nondegrade_interval; + + /** + * bit position (lsb is zero): Type of degradation + * 1 : Disable deblocking + * 2 : Faster inter prediction filters + * 3 : Fastest inter prediction filters + */ + WORD32 i4_degrade_type; + +} imvcd_set_degrade_mode_ip_t; + +typedef struct imvcd_set_degrade_mode_op_t +{ + UWORD32 u4_size; + + UWORD32 u4_error_code; +} imvcd_set_degrade_mode_op_t; + +typedef struct imvcd_flush_dec_ip_t +{ + ivd_ctl_flush_ip_t s_ivd_ip; +} imvcd_flush_dec_ip_t; + +typedef struct imvcd_flush_dec_op_t +{ + ivd_ctl_flush_op_t s_ivd_op; +} imvcd_flush_dec_op_t; + +typedef struct imvcd_get_buf_info_ip_t +{ + ivd_ctl_getbufinfo_ip_t s_ivd_ip; +} imvcd_get_buf_info_ip_t; + +typedef struct ivd_mvc_buf_info_t +{ + UWORD16 u2_num_views; +} ivd_mvc_buf_info_t; + +typedef struct imvcd_get_buf_info_op_t +{ + ivd_ctl_getbufinfo_op_t s_ivd_op; + + ivd_mvc_buf_info_t s_mvc_buf_info; + +} imvcd_get_buf_info_op_t; + +typedef struct imvcd_get_vui_ip_t +{ + UWORD32 u4_size; + + IVD_API_COMMAND_TYPE_T e_cmd; + + IVD_CONTROL_API_COMMAND_TYPE_T e_sub_cmd; + +} imvcd_get_vui_ip_t; + +typedef struct imvcd_get_vui_op_t +{ + bool b_is_vui_available; + + UWORD32 u4_error_code; + + UWORD8 u1_aspect_ratio_idc; + + UWORD16 u2_sar_width; + + UWORD16 u2_sar_height; + + UWORD8 u1_overscan_appropriate_flag; + + UWORD8 u1_video_format; + + UWORD8 u1_video_full_range_flag; + + UWORD8 u1_colour_primaries; + + UWORD8 u1_tfr_chars; + + UWORD8 u1_matrix_coeffs; + + UWORD8 u1_cr_top_field; + + UWORD8 u1_cr_bottom_field; + + UWORD32 u4_num_units_in_tick; + + UWORD32 u4_time_scale; + + UWORD8 u1_fixed_frame_rate_flag; + + UWORD8 u1_nal_hrd_params_present; + + UWORD8 u1_vcl_hrd_params_present; + + UWORD8 u1_low_delay_hrd_flag; + + UWORD8 u1_pic_struct_present_flag; + + UWORD8 u1_bitstream_restriction_flag; + + UWORD8 u1_mv_over_pic_boundaries_flag; + + UWORD32 u4_max_bytes_per_pic_denom; + + UWORD32 u4_max_bits_per_mb_denom; + + UWORD32 u4_log2_max_mv_length_horz; + + UWORD32 u4_log2_max_mv_length_vert; + + UWORD32 u4_num_reorder_frames; + + UWORD32 u4_max_dec_frame_buffering; + +} imvcd_get_vui_op_t; + +#endif diff --git a/decoder/mvc/imvcd_api.c b/decoder/mvc/imvcd_api.c new file mode 100644 index 0000000..9a0b4e1 --- /dev/null +++ b/decoder/mvc/imvcd_api.c @@ -0,0 +1,1588 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_api.c */ +/* */ +/* Description : Has all MVC API functions */ +/* */ +/* */ +/* List of Functions : */ +/* */ +/*****************************************************************************/ +#include + +#include "ih264_typedefs.h" +#include "iv.h" +#include "ivd.h" +#include "imvcd.h" +#include "ih264_debug.h" +#include "ih264_disp_mgr.h" +#include "ih264_error.h" +#include "ih264_buf_mgr.h" +#include "ih264_platform_macros.h" +#include "ih264d_inter_pred.h" +#include "ih264d_structs.h" +#include "ih264d_deblocking.h" +#include "ih264d_error_handler.h" +#include "ih264d_function_selector.h" +#include "ih264d_nal.h" +#include "ih264d_parse_cavlc.h" +#include "ih264d_parse_headers.h" +#include "ih264d_tables.h" +#include "ih264d_thread_compute_bs.h" +#include "ih264d_utils.h" +#include "ih264d_api_utils.h" +#include "ithread.h" +#include "imvcd_api_utils.h" +#include "imvcd_dpb_manager.h" +#include "imvcd_error_handler.h" +#include "imvcd_nalu_parser.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +static void imvcd_free_static_bufs(iv_obj_t *ps_dec_hdl) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt; + dec_struct_t *ps_view_ctxt; + + FT_ALIGNED_FREE *pf_aligned_free; + + void *pv_mem_ctxt; + + if(!ps_dec_hdl) + { + return; + } + + ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + + if(!ps_mvcd_ctxt) + { + return; + } + + ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + pf_aligned_free = ps_view_ctxt->pf_aligned_free; + pv_mem_ctxt = ps_view_ctxt->pv_mem_ctxt; + + imvcd_free_dynamic_bufs(ps_mvcd_ctxt); + + imvcd_bitsteam_buf_free(ps_view_ctxt); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_left_mvpred_addr); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu4_wts_ofsts_mat); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu4_mbaff_wt_mat); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_init_dpb_base); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_temp_mc_buffer); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pi2_pred1); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_ref_buff_base); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_left_mb_ctxt_info); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->p_cabac_ctxt_table_t); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ppv_map_ref_idx_to_poc_base); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_bits_buf_static); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pv_scratch_sps_pps); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_bitstrm); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_dpb_cmds); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_sei_parse); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_sei); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_dec_err_status); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_pred); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pv_bs_deblk_thread_handle); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pv_dec_thread_handle); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_pps); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_sps); + + ih264_buf_mgr_free(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_mem); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_mem); + + ih264_buf_mgr_free(ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_mem); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_mem); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_mvcd_ctxt->ps_dpb_mgr); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_mvcd_ctxt); + + if(ps_dec_hdl) + { + pf_aligned_free(pv_mem_ctxt, ps_dec_hdl); + } +} + +static IV_API_CALL_STATUS_T imvcd_view_ctxt_init(imvcd_create_ip_t *ps_ip, + dec_struct_t *ps_view_ctxt) +{ + pocstruct_t *ps_prev_poc, *ps_cur_poc; + + WORD32 i4_mem_size; + void *pv_buf; + + FT_ALIGNED_ALLOC *pf_aligned_alloc = ps_ip->s_ivd_ip.pf_aligned_alloc; + + void *pv_mem_ctxt = ps_ip->s_ivd_ip.pv_mem_ctxt; + const WORD32 i4_default_alignment = 128; + + ps_view_ctxt->u4_share_disp_buf = 0; + ps_view_ctxt->u1_chroma_format = ps_ip->s_ivd_ip.e_output_format; + + ps_view_ctxt->pf_aligned_alloc = pf_aligned_alloc; + ps_view_ctxt->pf_aligned_free = ps_ip->s_ivd_ip.pf_aligned_free; + ps_view_ctxt->pv_mem_ctxt = ps_ip->s_ivd_ip.pv_mem_ctxt; + + i4_mem_size = ((sizeof(dec_seq_params_t)) * MAX_NUM_SEQ_PARAMS); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_sps = pv_buf; + + i4_mem_size = (sizeof(dec_pic_params_t)) * MAX_NUM_PIC_PARAMS; + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_pps = pv_buf; + + i4_mem_size = ithread_get_handle_size(); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pv_dec_thread_handle = pv_buf; + + i4_mem_size = ithread_get_handle_size(); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pv_bs_deblk_thread_handle = pv_buf; + + i4_mem_size = sizeof(pred_info_t) * 2 * 32; + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_pred = pv_buf; + + ps_view_ctxt->pv_disp_buf_mgr = NULL; + + ps_view_ctxt->pv_pic_buf_mgr = NULL; + + ps_view_ctxt->ps_pic_buf_base = NULL; + + i4_mem_size = sizeof(dec_err_status_t); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_dec_err_status = (dec_err_status_t *) pv_buf; + + i4_mem_size = sizeof(sei); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_sei = (sei *) pv_buf; + + i4_mem_size = sizeof(sei); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_sei_parse = (sei *) pv_buf; + + i4_mem_size = sizeof(dpb_commands_t); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_dpb_cmds = (dpb_commands_t *) pv_buf; + + i4_mem_size = sizeof(dec_bit_stream_t); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_bitstrm = (dec_bit_stream_t *) pv_buf; + + i4_mem_size = MAX(sizeof(dec_seq_params_t), sizeof(dec_pic_params_t)); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pv_scratch_sps_pps = pv_buf; + + ps_view_ctxt->u4_static_bits_buf_size = 256000; + pv_buf = + pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, ps_view_ctxt->u4_static_bits_buf_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, ps_view_ctxt->u4_static_bits_buf_size); + ps_view_ctxt->pu1_bits_buf_static = pv_buf; + + i4_mem_size = (TOTAL_LIST_ENTRIES + PAD_MAP_IDX_POC) * sizeof(void *); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + ps_view_ctxt->ppv_map_ref_idx_to_poc_base = pv_buf; + ps_view_ctxt->ppv_map_ref_idx_to_poc = + ps_view_ctxt->ppv_map_ref_idx_to_poc_base + OFFSET_MAP_IDX_POC; + memset(ps_view_ctxt->ppv_map_ref_idx_to_poc_base, 0, i4_mem_size); + + i4_mem_size = (sizeof(bin_ctxt_model_t) * NUM_CABAC_CTXTS); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->p_cabac_ctxt_table_t = pv_buf; + + i4_mem_size = sizeof(ctxt_inc_mb_info_t); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_left_mb_ctxt_info = pv_buf; + + i4_mem_size = MAX_REF_BUF_SIZE * 2; + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu1_ref_buff_base = pv_buf; + ps_view_ctxt->pu1_ref_buff = ps_view_ctxt->pu1_ref_buff_base + MAX_REF_BUF_SIZE; + + i4_mem_size = sizeof(WORD16) * PRED_BUFFER_WIDTH * PRED_BUFFER_HEIGHT * 2; + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pi2_pred1 = pv_buf; + + i4_mem_size = sizeof(UWORD8) * (MB_LUM_SIZE); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu1_temp_mc_buffer = pv_buf; + + i4_mem_size = (sizeof(UWORD32) * 2 * 3 * ((MAX_FRAMES << 1) * (MAX_FRAMES << 1)) * 2); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu4_mbaff_wt_mat = pv_buf; + + i4_mem_size = sizeof(UWORD32) * 2 * 3 * ((MAX_FRAMES << 1) * (MAX_FRAMES << 1)); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu4_wts_ofsts_mat = pv_buf; + + i4_mem_size = (sizeof(neighbouradd_t) << 2); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_left_mvpred_addr = pv_buf; + + ps_view_ctxt->pv_mv_buf_mgr = NULL; + + ps_view_ctxt->ps_col_mv_base = NULL; + + ps_view_ctxt->init_done = 0; + ps_view_ctxt->u4_num_cores = 1; + ps_view_ctxt->u2_pic_ht = ps_view_ctxt->u2_pic_wd = 0; + ps_view_ctxt->u1_separate_parse = DEFAULT_SEPARATE_PARSE; + ps_view_ctxt->u4_app_disable_deblk_frm = 0; + ps_view_ctxt->i4_degrade_type = 0; + ps_view_ctxt->i4_degrade_pics = 0; + + memset(ps_view_ctxt->ps_pps, 0, ((sizeof(dec_pic_params_t)) * MAX_NUM_PIC_PARAMS)); + memset(ps_view_ctxt->ps_sps, 0, ((sizeof(dec_seq_params_t)) * MAX_NUM_SEQ_PARAMS)); + + ps_view_ctxt->p_DeblockPicture[0] = ih264d_deblock_picture_non_mbaff; + ps_view_ctxt->p_DeblockPicture[1] = ih264d_deblock_picture_mbaff; + ps_view_ctxt->s_cab_dec_env.pv_codec_handle = ps_view_ctxt; + ps_view_ctxt->u4_num_fld_in_frm = 0; + ps_view_ctxt->ps_sei->u1_is_valid = 0; + ps_view_ctxt->ps_cur_pps = NULL; + ps_view_ctxt->ps_cur_sps = NULL; + ps_view_ctxt->ps_cur_slice = NULL; + ps_view_ctxt->u1_init_dec_flag = 0; + ps_view_ctxt->u1_first_slice_in_stream = 1; + ps_view_ctxt->u1_last_pic_not_decoded = 0; + ps_view_ctxt->u4_app_disp_width = 0; + ps_view_ctxt->i4_header_decoded = 0; + ps_view_ctxt->u4_total_frames_decoded = 0; + ps_view_ctxt->i4_error_code = 0; + ps_view_ctxt->i4_content_type = IV_CONTENTTYPE_NA; + ps_view_ctxt->ps_dec_err_status->u1_err_flag = ACCEPT_ALL_PICS; + ps_view_ctxt->ps_dec_err_status->u1_cur_pic_type = PIC_TYPE_UNKNOWN; + ps_view_ctxt->ps_dec_err_status->u4_frm_sei_sync = SYNC_FRM_DEFAULT; + ps_view_ctxt->ps_dec_err_status->u4_cur_frm = INIT_FRAME; + ps_view_ctxt->ps_dec_err_status->u1_pic_aud_i = PIC_TYPE_UNKNOWN; + ps_view_ctxt->u1_pr_sl_type = 0xFF; + ps_view_ctxt->u2_mbx = 0xffff; + ps_view_ctxt->u2_mby = 0; + ps_view_ctxt->u2_total_mbs_coded = 0; + + ps_prev_poc = &ps_view_ctxt->s_prev_pic_poc; + ps_cur_poc = &ps_view_ctxt->s_cur_pic_poc; + ps_prev_poc->i4_pic_order_cnt_lsb = ps_cur_poc->i4_pic_order_cnt_lsb = 0; + ps_prev_poc->i4_pic_order_cnt_msb = ps_cur_poc->i4_pic_order_cnt_msb = 0; + ps_prev_poc->i4_delta_pic_order_cnt_bottom = ps_cur_poc->i4_delta_pic_order_cnt_bottom = 0; + ps_prev_poc->i4_delta_pic_order_cnt[0] = ps_cur_poc->i4_delta_pic_order_cnt[0] = 0; + ps_prev_poc->i4_delta_pic_order_cnt[1] = ps_cur_poc->i4_delta_pic_order_cnt[1] = 0; + ps_prev_poc->u1_mmco_equalto5 = ps_cur_poc->u1_mmco_equalto5 = 0; + ps_prev_poc->i4_top_field_order_count = ps_cur_poc->i4_top_field_order_count = 0; + ps_prev_poc->i4_bottom_field_order_count = ps_cur_poc->i4_bottom_field_order_count = 0; + ps_prev_poc->u1_bot_field = ps_cur_poc->u1_bot_field = 0; + ps_prev_poc->u1_mmco_equalto5 = ps_cur_poc->u1_mmco_equalto5 = 0; + ps_prev_poc->i4_prev_frame_num_ofst = ps_cur_poc->i4_prev_frame_num_ofst = 0; + + ps_view_ctxt->i4_max_poc = 0; + ps_view_ctxt->i4_prev_max_display_seq = 0; + ps_view_ctxt->u1_recon_mb_grp = 4; + ps_view_ctxt->i4_reorder_depth = -1; + ps_view_ctxt->u1_second_field = 0; + ps_view_ctxt->s_prev_seq_params.u1_eoseq_pending = 0; + ps_view_ctxt->u2_crop_offset_y = 0; + ps_view_ctxt->u2_crop_offset_uv = 0; + ps_view_ctxt->i4_vui_frame_rate = -1; + ps_view_ctxt->i4_pic_type = NA_SLICE; + ps_view_ctxt->i4_frametype = IV_NA_FRAME; + ps_view_ctxt->i4_content_type = IV_CONTENTTYPE_NA; + ps_view_ctxt->u1_res_changed = 0; + ps_view_ctxt->u1_frame_decoded_flag = 0; + ps_view_ctxt->u4_skip_frm_mask = SKIP_NONE; + + ps_view_ctxt->pf_cavlc_4x4res_block[0] = ih264d_cavlc_4x4res_block_totalcoeff_1; + ps_view_ctxt->pf_cavlc_4x4res_block[1] = ih264d_cavlc_4x4res_block_totalcoeff_2to10; + ps_view_ctxt->pf_cavlc_4x4res_block[2] = ih264d_cavlc_4x4res_block_totalcoeff_11to16; + ps_view_ctxt->pf_cavlc_parse4x4coeff[0] = ih264d_cavlc_parse4x4coeff_n0to7; + ps_view_ctxt->pf_cavlc_parse4x4coeff[1] = ih264d_cavlc_parse4x4coeff_n8; + ps_view_ctxt->pf_cavlc_parse_8x8block[0] = ih264d_cavlc_parse_8x8block_none_available; + ps_view_ctxt->pf_cavlc_parse_8x8block[1] = ih264d_cavlc_parse_8x8block_left_available; + ps_view_ctxt->pf_cavlc_parse_8x8block[2] = ih264d_cavlc_parse_8x8block_top_available; + ps_view_ctxt->pf_cavlc_parse_8x8block[3] = ih264d_cavlc_parse_8x8block_both_available; + + ps_view_ctxt->pf_fill_bs1[0][0] = ih264d_fill_bs1_16x16mb_pslice; + ps_view_ctxt->pf_fill_bs1[0][1] = ih264d_fill_bs1_non16x16mb_pslice; + ps_view_ctxt->pf_fill_bs1[1][0] = ih264d_fill_bs1_16x16mb_bslice; + ps_view_ctxt->pf_fill_bs1[1][1] = ih264d_fill_bs1_non16x16mb_bslice; + ps_view_ctxt->pf_fill_bs_xtra_left_edge[0] = ih264d_fill_bs_xtra_left_edge_cur_frm; + ps_view_ctxt->pf_fill_bs_xtra_left_edge[1] = ih264d_fill_bs_xtra_left_edge_cur_fld; + + ps_view_ctxt->u2_prv_frame_num = 0; + ps_view_ctxt->u1_top_bottom_decoded = 0; + ps_view_ctxt->u1_dangling_field = 0; + ps_view_ctxt->s_cab_dec_env.cabac_table = gau4_ih264d_cabac_table; + ps_view_ctxt->pu1_left_mv_ctxt_inc = ps_view_ctxt->u1_left_mv_ctxt_inc_arr[0]; + ps_view_ctxt->pi1_left_ref_idx_ctxt_inc = &ps_view_ctxt->i1_left_ref_idx_ctx_inc_arr[0][0]; + ps_view_ctxt->pu1_left_yuv_dc_csbp = &ps_view_ctxt->u1_yuv_dc_csbp_topmb; + ps_view_ctxt->u1_flushfrm = 0; + ps_view_ctxt->s_cab_dec_env.pv_codec_handle = ps_view_ctxt; + ps_view_ctxt->ps_bitstrm->pv_codec_handle = ps_view_ctxt; + + memset(ps_view_ctxt->disp_bufs, 0, (MAX_DISP_BUFS_NEW) * sizeof(disp_buf_t)); + memset(ps_view_ctxt->u4_disp_buf_mapping, 0, (MAX_DISP_BUFS_NEW) * sizeof(UWORD32)); + memset(ps_view_ctxt->u4_disp_buf_to_be_freed, 0, (MAX_DISP_BUFS_NEW) * sizeof(UWORD32)); + + ih264d_init_arch(ps_view_ctxt); + ih264d_init_function_ptr(ps_view_ctxt); + ps_view_ctxt->e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + ps_view_ctxt->init_done = 1; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctxt_init(imvcd_create_ip_t *ps_ip, mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i4_mem_size; + void *pv_buf; + + FT_ALIGNED_ALLOC *pf_aligned_alloc = ps_ip->s_ivd_ip.pf_aligned_alloc; + + void *pv_mem_ctxt = ps_ip->s_ivd_ip.pv_mem_ctxt; + const WORD32 i4_default_alignment = 128; + + memset(ps_mvcd_ctxt, 0, sizeof(ps_mvcd_ctxt[0])); + + i4_mem_size = sizeof(mvc_dpb_manager_t); + ps_mvcd_ctxt->ps_dpb_mgr = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == ps_mvcd_ctxt->ps_dpb_mgr), IV_FAIL); + memset(ps_mvcd_ctxt->ps_dpb_mgr, 0, i4_mem_size); + + imvcd_init_dpb_mgr(ps_mvcd_ctxt->ps_dpb_mgr, &ps_mvcd_ctxt->s_mvc_au_buf_mgr, + &ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr, &ps_mvcd_ctxt->s_mvc_disp_buf_mgr); + + ih264_disp_mgr_init(&ps_mvcd_ctxt->s_mvc_disp_buf_mgr); + + i4_mem_size = sizeof(buf_mgr_t) + ithread_get_mutex_lock_size(); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_mem = pv_buf; + ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt = pv_buf; + + ih264_buf_mgr_init(ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_mem); + + i4_mem_size = sizeof(buf_mgr_t) + ithread_get_mutex_lock_size(); + pv_buf = pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_mem = pv_buf; + ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt = pv_buf; + + ih264_buf_mgr_init(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_mem); + + if(IV_SUCCESS != imvcd_view_ctxt_init(ps_ip, &ps_mvcd_ctxt->s_view_dec_ctxt)) + { + return IV_FAIL; + } + + ps_mvcd_ctxt->u2_num_views = 0; + ps_mvcd_ctxt->u2_num_views_decoded = 0; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_allocate_static_bufs(imvcd_create_ip_t *ps_ip, + imvcd_create_op_t *ps_op) +{ + iv_obj_t *ps_dec_hdl; + mvc_dec_ctxt_t *ps_mvcd_ctxt; + + WORD32 i4_mem_size; + + FT_ALIGNED_ALLOC *pf_aligned_alloc = ps_ip->s_ivd_ip.pf_aligned_alloc; + + void *pv_mem_ctxt = ps_ip->s_ivd_ip.pv_mem_ctxt; + const WORD32 i4_default_alignment = 128; + + i4_mem_size = sizeof(ps_dec_hdl[0]); + ps_op->s_ivd_op.pv_handle = ps_dec_hdl = + (iv_obj_t *) pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + + if(NULL == ps_dec_hdl) + { + return IV_FAIL; + } + + i4_mem_size = sizeof(ps_mvcd_ctxt[0]); + ps_dec_hdl->pv_codec_handle = ps_mvcd_ctxt = + (mvc_dec_ctxt_t *) pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + + if(NULL == ps_mvcd_ctxt) + { + return IV_FAIL; + } + + if(IV_SUCCESS != imvcd_ctxt_init(ps_ip, ps_mvcd_ctxt)) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} + +/* Description - 'Create' API for MVC Decoder */ +static IV_API_CALL_STATUS_T imvcd_create(imvcd_create_ip_t *ps_ip, imvcd_create_op_t *ps_op) +{ + if(IV_SUCCESS != imvcd_check_create_structs(ps_ip, ps_op)) + { + return IV_FAIL; + } + + if(IV_SUCCESS != imvcd_allocate_static_bufs(ps_ip, ps_op)) + { + imvcd_free_static_bufs((iv_obj_t *) ps_op->s_ivd_op.pv_handle); + + return IV_FAIL; + } + + return IV_SUCCESS; +} + +/* Description - 'Delete' API for MVC Decoder */ +static IV_API_CALL_STATUS_T imvcd_delete(iv_obj_t *ps_dec_hdl) +{ + if(IV_SUCCESS != imvcd_check_dec_handle(ps_dec_hdl)) + { + return IV_FAIL; + } + + imvcd_free_static_bufs(ps_dec_hdl); + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_flush_mode_decode(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_op_t *ps_op) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + if(!ps_view_ctxt->u1_init_dec_flag) + { + ps_view_ctxt->u1_flushfrm = 0; + ps_mvcd_ctxt->b_flush_enabled = false; + ps_op->s_ivd_op.u4_output_present = 0; + + return IV_FAIL; + } + + if(IV_SUCCESS != imvcd_get_next_display_au_buf(ps_mvcd_ctxt)) + { + ps_view_ctxt->u1_flushfrm = 0; + ps_mvcd_ctxt->b_flush_enabled = false; + ps_op->s_ivd_op.u4_output_present = false; + + return IV_SUCCESS; + } + + ih264d_export_sei_params(&ps_op->s_ivd_op.s_sei_decode_op, ps_view_ctxt); + + ps_op->s_ivd_op.u4_pic_wd = ps_view_ctxt->u2_disp_width; + ps_op->s_ivd_op.u4_pic_ht = ps_view_ctxt->u2_disp_height; + ps_op->s_ivd_op.u4_ts = ps_view_ctxt->s_disp_op.u4_ts; + ps_op->s_ivd_op.u4_output_present = 1; + ps_op->s_ivd_op.e_output_format = IV_YUV_420P; + + imvcd_convert_to_app_disp_buf(ps_mvcd_ctxt, ps_op->ps_view_disp_bufs); + + return IV_SUCCESS; +} + +static void imvcd_fill_output_struct_from_context(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_op_t *ps_op) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + if((ps_op->s_ivd_op.u4_error_code & 0xff) != ERROR_DYNAMIC_RESOLUTION_NOT_SUPPORTED) + { + ps_op->s_ivd_op.u4_pic_wd = ps_view_ctxt->u2_disp_width; + ps_op->s_ivd_op.u4_pic_ht = ps_view_ctxt->u2_disp_height; + } + + ps_op->s_ivd_op.u4_output_present = ps_view_ctxt->u4_output_present; + + ps_op->s_ivd_op.e_output_format = IV_YUV_420P; + + imvcd_convert_to_app_disp_buf(ps_mvcd_ctxt, ps_op->ps_view_disp_bufs); + + ih264d_export_sei_params(&ps_op->s_ivd_op.s_sei_decode_op, ps_view_ctxt); +} + +static void imvcd_video_decode_clean_return(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ih264d_signal_decode_thread(ps_view_ctxt); + ih264d_signal_bs_deblk_thread(ps_view_ctxt); + + imvcd_fill_output_struct_from_context(ps_mvcd_ctxt, ps_op); + + ps_op->s_ivd_op.u4_frame_decoded_flag = 0; + ps_op->s_ivd_op.u4_num_bytes_consumed = ps_ip->s_ivd_ip.u4_num_Bytes; +} + +static FORCEINLINE void imvcd_update_num_pps(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_mvcd_ctxt->u1_num_pps = 0; + + for(i = 0; i < MAX_NUM_PIC_PARAMS; i++) + { + if(ps_view_ctxt->ps_pps[i].u1_is_valid) + { + UWORD8 u1_sps_id = ps_view_ctxt->ps_pps[i].ps_sps->u1_seq_parameter_set_id; + + if(ps_mvcd_ctxt->as_subset_sps[u1_sps_id].s_sps_data.u1_is_valid) + { + ps_mvcd_ctxt->aps_pps_id_to_subset_sps_map[i] = + &ps_mvcd_ctxt->as_subset_sps[u1_sps_id]; + } + + ps_mvcd_ctxt->u1_num_pps++; + } + } +} + +static FORCEINLINE void imvcd_update_num_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_mvcd_ctxt->u1_num_sps = 0; + + for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++) + { + if(ps_view_ctxt->ps_sps[i].u1_is_valid) + { + ps_mvcd_ctxt->u1_num_sps++; + } + } +} + +static FORCEINLINE void imvcd_update_num_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + ps_mvcd_ctxt->u1_num_subset_sps = 0; + + for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++) + { + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid) + { + ps_mvcd_ctxt->u1_num_subset_sps++; + } + } +} + +static IV_API_CALL_STATUS_T imvcd_view_decode(iv_obj_t *ps_dec_hdl, imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op) +{ + UWORD8 *pu1_input_buffer; + UWORD8 *pu1_bitstream_buf; + UWORD32 u4_bitstream_buf_size; + WORD32 i4_nalu_length; + UWORD32 u4_length_of_start_code; + WORD32 i4_error_code; + + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UWORD32 u4_num_bytes_consumed = 0; + UWORD32 u4_num_bytes_remaining = ps_ip->s_ivd_ip.u4_num_Bytes; + bool b_first_start_code_found = false; + bool b_frame_data_left = true; + bool b_header_data_left = true; + UWORD32 u4_next_is_aud = 0; + + ASSERT(u4_num_bytes_remaining > 0); + + imvcd_view_init(ps_mvcd_ctxt); + + do + { + pu1_input_buffer = ((UWORD8 *) ps_ip->s_ivd_ip.pv_stream_buffer) + u4_num_bytes_consumed; + + if(!ps_view_ctxt->pu1_bits_buf_dynamic && + is_header_decoded(ps_view_ctxt->i4_header_decoded, PPS)) + { + if(IV_SUCCESS != + imvcd_bitstream_buf_alloc( + ps_view_ctxt, is_header_decoded(ps_view_ctxt->i4_header_decoded, SUBSET_SPS) + ? ps_mvcd_ctxt->u2_num_views + : 1)) + { + return IV_FAIL; + } + } + + if(ps_view_ctxt->pu1_bits_buf_dynamic) + { + pu1_bitstream_buf = ps_view_ctxt->pu1_bits_buf_dynamic; + u4_bitstream_buf_size = ps_view_ctxt->u4_dynamic_bits_buf_size; + } + else + { + pu1_bitstream_buf = ps_view_ctxt->pu1_bits_buf_static; + u4_bitstream_buf_size = ps_view_ctxt->u4_static_bits_buf_size; + } + + i4_nalu_length = ih264d_find_start_code(pu1_input_buffer, 0, u4_num_bytes_remaining, + &u4_length_of_start_code, &u4_next_is_aud); + + if(i4_nalu_length == -1) + { + i4_nalu_length = 0; + } + + if((0 != u4_next_is_aud) && (1 != u4_next_is_aud)) + { + return IV_FAIL; + } + + /* Ignore bytes beyond the allocated size of intermediate buffer */ + /* Since 8 bytes are read ahead, ensure 8 bytes are free at the + end of the buffer, which will be memset to 0 after emulation prevention */ + i4_nalu_length = MIN((UWORD32) i4_nalu_length, u4_bitstream_buf_size - 8); + + if(i4_nalu_length) + { + memcpy(pu1_bitstream_buf, pu1_input_buffer + u4_length_of_start_code, i4_nalu_length); + + /* Decoder may read extra 8 bytes near end of the frame */ + if(((UWORD32) (i4_nalu_length + 8)) < u4_bitstream_buf_size) + { + memset(pu1_bitstream_buf + i4_nalu_length, 0, 8 * sizeof(pu1_bitstream_buf[0])); + } + + b_first_start_code_found = true; + } + else + { + if(!b_first_start_code_found) + { + ps_view_ctxt->i4_error_code = ERROR_START_CODE_NOT_FOUND; + ps_op->s_ivd_op.u4_error_code |= 1 << IVD_INSUFFICIENTDATA; + + if(ps_view_ctxt->u4_pic_buf_got == 0) + { + imvcd_fill_output_struct_from_context(ps_mvcd_ctxt, ps_op); + + ps_op->s_ivd_op.u4_error_code = ps_view_ctxt->i4_error_code; + + imvcd_video_decode_clean_return(ps_mvcd_ctxt, ps_ip, ps_op); + + return IV_FAIL; + } + else + { + ps_view_ctxt->u1_pic_decode_done = 1; + + continue; + } + } + else + { + /* a start code has already been found earlier in the same process + * call*/ + b_frame_data_left = false; + b_header_data_left = false; + + if(!ps_view_ctxt->i4_decode_header && !ps_view_ctxt->u4_pic_buf_got) + { + ps_op->s_ivd_op.u4_error_code = ih264d_map_error(ERROR_UNKNOWN_NAL); + + imvcd_video_decode_clean_return(ps_mvcd_ctxt, ps_ip, ps_op); + + return IV_FAIL; + } + + continue; + } + } + + ps_mvcd_ctxt->ae_nalu_id[ps_mvcd_ctxt->u2_num_views_decoded] = + NAL_UNIT_TYPE(pu1_bitstream_buf[0]); + ps_mvcd_ctxt->au1_nal_ref_idc[ps_mvcd_ctxt->u2_num_views_decoded] = + NAL_REF_IDC(pu1_bitstream_buf[0]); + + if(!is_mvc_nalu(ps_mvcd_ctxt->ae_nalu_id[ps_mvcd_ctxt->u2_num_views_decoded])) + { + ivd_video_decode_op_t s_avc_op; + + i4_error_code = + ih264d_parse_nal_unit(ps_dec_hdl, &s_avc_op, pu1_bitstream_buf, i4_nalu_length); + } + else + { + i4_error_code = imvcd_nalu_parser(ps_mvcd_ctxt, pu1_bitstream_buf, i4_nalu_length); + } + + if(OK != i4_error_code) + { + ps_op->s_ivd_op.u4_error_code = i4_error_code; + + imvcd_video_decode_clean_return(ps_mvcd_ctxt, ps_ip, ps_op); + + return IV_FAIL; + } + else if(PPS == ps_mvcd_ctxt->ae_nalu_id[ps_mvcd_ctxt->u2_num_views_decoded]) + { + imvcd_update_num_pps(ps_mvcd_ctxt); + } + else if(SPS == ps_mvcd_ctxt->ae_nalu_id[ps_mvcd_ctxt->u2_num_views_decoded]) + { + imvcd_update_num_sps(ps_mvcd_ctxt); + } + else if(SUBSET_SPS == ps_mvcd_ctxt->ae_nalu_id[ps_mvcd_ctxt->u2_num_views_decoded]) + { + imvcd_update_num_subset_sps(ps_mvcd_ctxt); + } + + b_header_data_left = ps_view_ctxt->i4_decode_header && + (!is_header_decoded(ps_view_ctxt->i4_header_decoded, SPS) || + !is_header_decoded(ps_view_ctxt->i4_header_decoded, PPS)) && + (u4_num_bytes_consumed < ps_ip->s_ivd_ip.u4_num_Bytes); + b_frame_data_left = (!ps_view_ctxt->i4_decode_header && + (!ps_view_ctxt->u1_pic_decode_done || u4_next_is_aud)) && + (u4_num_bytes_consumed < ps_ip->s_ivd_ip.u4_num_Bytes); + + u4_num_bytes_consumed += i4_nalu_length + u4_length_of_start_code; + u4_num_bytes_remaining -= i4_nalu_length + u4_length_of_start_code; + + } while(b_header_data_left || b_frame_data_left); + + if((i4_error_code == IVD_RES_CHANGED) || (i4_error_code == IVD_MEM_ALLOC_FAILED) || + (i4_error_code == ERROR_UNAVAIL_PICBUF_T) || (i4_error_code == ERROR_UNAVAIL_MVBUF_T) || + (i4_error_code == ERROR_INV_SPS_PPS_T)) + { + ih264d_signal_decode_thread(ps_view_ctxt); + + if(ps_view_ctxt->u4_num_cores == 3) + { + ih264d_signal_bs_deblk_thread(ps_view_ctxt); + } + + /* dont consume bitstream for change in resolution case */ + if(i4_error_code == IVD_RES_CHANGED) + { + ps_op->s_ivd_op.u4_num_bytes_consumed -= u4_num_bytes_consumed; + } + + imvcd_video_decode_clean_return(ps_mvcd_ctxt, ps_ip, ps_op); + + return IV_FAIL; + } + + if(ps_view_ctxt->u1_separate_parse) + { + if(ps_view_ctxt->u4_num_cores == 2) + { + if((ps_view_ctxt->u4_nmb_deblk == 0) && (ps_view_ctxt->u4_start_recon_deblk == 1)) + { + tfr_ctxt_t s_tfr_ctxt; + + UWORD32 u4_num_mbs, u4_max_addr; + + tfr_ctxt_t *ps_tfr_cxt = &s_tfr_ctxt; + pad_mgr_t *ps_pad_mgr = &ps_view_ctxt->s_pad_mgr; + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + + /*BS is done for all mbs while parsing*/ + u4_max_addr = (ps_view_ctxt->u2_frm_wd_in_mbs * ps_view_ctxt->u2_frm_ht_in_mbs) - 1; + ps_view_ctxt->u4_cur_bs_mb_num = u4_max_addr + 1; + + ps_view_ctxt->ps_cur_pic = &ps_view_ctxt->s_cur_pic; + imvcd_convert_au_buf_to_view_buf(ps_mvcd_ctxt->ps_cur_au, &ps_view_ctxt->s_cur_pic, + ps_mvcd_ctxt->u2_num_views_decoded, + ps_cur_nalu_mvc_ext->u2_view_id); + + ih264d_init_deblk_tfr_ctxt(ps_view_ctxt, ps_pad_mgr, ps_tfr_cxt, + ps_view_ctxt->u2_frm_wd_in_mbs, 0); + + u4_num_mbs = u4_max_addr - ps_view_ctxt->u4_cur_deblk_mb_num + 1; + + if(u4_num_mbs != 0) + { + ih264d_check_mb_map_deblk(ps_view_ctxt, u4_num_mbs, ps_tfr_cxt, 1); + } + + ps_view_ctxt->u4_start_recon_deblk = 0; + } + } + + ih264d_signal_decode_thread(ps_view_ctxt); + + if(ps_view_ctxt->u4_num_cores == 3) + { + ih264d_signal_bs_deblk_thread(ps_view_ctxt); + } + } + + DATA_SYNC(); + + // Report if header (sps and pps) has not been decoded yet + if(ps_view_ctxt->i4_decode_header && + (!is_header_decoded(ps_view_ctxt->i4_header_decoded, SPS) && + !is_header_decoded(ps_view_ctxt->i4_header_decoded, PPS))) + { + ps_op->s_ivd_op.u4_error_code |= (1 << IVD_INSUFFICIENTDATA); + + imvcd_video_decode_clean_return(ps_mvcd_ctxt, ps_ip, ps_op); + + return IV_FAIL; + } + + if(ps_view_ctxt->u4_pic_buf_got) + { + ps_view_ctxt->u1_top_bottom_decoded = TOP_FIELD_ONLY | BOT_FIELD_ONLY; + + if(((ps_view_ctxt->ps_dec_err_status->u1_err_flag & REJECT_CUR_PIC) == 0) && + ps_view_ctxt->u1_pic_decode_done) + { + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + + if(!ps_mvcd_ctxt->au1_nal_ref_idc[ps_mvcd_ctxt->u2_num_views_decoded] && + ps_cur_nalu_mvc_ext->u1_inter_view_flag) + { + ps_view_ctxt->ps_cur_slice->u1_nal_ref_idc = 1; + } + + /* Padding only. Deblk has happened already. */ + ih264d_deblock_picture_progressive(ps_view_ctxt); + + if(!ps_mvcd_ctxt->au1_nal_ref_idc[ps_mvcd_ctxt->u2_num_views_decoded] && + ps_cur_nalu_mvc_ext->u1_inter_view_flag) + { + ps_view_ctxt->ps_cur_slice->u1_nal_ref_idc = 0; + } + } + + /*Update the i4_frametype at the end of picture*/ + if(imvcd_is_idr_au(ps_mvcd_ctxt)) + { + ps_view_ctxt->i4_frametype = IV_IDR_FRAME; + } + else if(ps_view_ctxt->i4_pic_type == B_SLICE) + { + ps_view_ctxt->i4_frametype = IV_B_FRAME; + } + else if(ps_view_ctxt->i4_pic_type == P_SLICE) + { + ps_view_ctxt->i4_frametype = IV_P_FRAME; + } + else if(ps_view_ctxt->i4_pic_type == I_SLICE) + { + ps_view_ctxt->i4_frametype = IV_I_FRAME; + } + + ps_view_ctxt->i4_content_type = ps_view_ctxt->ps_cur_slice->u1_field_pic_flag; + } + + /* close deblock thread if it is not closed yet*/ + if(ps_view_ctxt->u4_num_cores == 3) + { + ih264d_signal_bs_deblk_thread(ps_view_ctxt); + } + + if(ps_view_ctxt->u4_dec_thread_created) + { + ih264d_signal_decode_thread(ps_view_ctxt); + } + + if(ps_view_ctxt->u4_bs_deblk_thread_created) + { + ih264d_signal_bs_deblk_thread(ps_view_ctxt); + } + + ps_op->s_ivd_op.u4_num_bytes_consumed = u4_num_bytes_consumed; + + DATA_SYNC(); + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_finish_au_decode(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_op_t *ps_op) +{ + WORD32 i4_error_code; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + mvc_au_buffer_t *ps_cur_au = ps_mvcd_ctxt->ps_cur_au; + mvc_dpb_manager_t *ps_dpb_mgr = ps_mvcd_ctxt->ps_dpb_mgr; + + bool b_is_idr = imvcd_is_idr_au(ps_mvcd_ctxt); + bool b_is_ref_au = !!ps_mvcd_ctxt->au1_nal_ref_idc[ps_mvcd_ctxt->u2_num_views - 1]; + WORD64 i8_display_poc = ps_view_ctxt->i4_prev_max_display_seq + ps_cur_au->i4_poc; + + imvcd_dpb_delete_nonref_nondisplay_pics(ps_dpb_mgr); + + if(ps_cur_slice->u1_mmco_equalto5 || b_is_idr) + { + ps_cur_au->i4_poc = 0; + ps_cur_au->i4_avg_poc = 0; + + if(ps_view_ctxt->u2_total_mbs_coded == (ps_view_ctxt->ps_cur_sps->u2_max_mb_addr + 1)) + { + imvcd_reset_dpb(ps_dpb_mgr); + } + + imvcd_dpb_release_display_bufs(ps_dpb_mgr); + } + + if(IVD_DECODE_FRAME_OUT != ps_view_ctxt->e_frm_out_mode) + { + i4_error_code = imvcd_dpb_assign_display_seq(ps_dpb_mgr); + + if(OK != i4_error_code) + { + return IV_FAIL; + } + } + + if(b_is_ref_au) + { + ih264_buf_mgr_set_status(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, + ps_cur_au->i4_pic_buf_id, BUF_MGR_REF); + + ih264_buf_mgr_set_status(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, + ps_cur_au->i4_mv_buf_id, BUF_MGR_REF); + + ps_view_ctxt->au1_pic_buf_ref_flag[ps_cur_au->i4_pic_buf_id] = 1; + } + else + { + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, + ps_cur_au->i4_pic_buf_id, BUF_MGR_REF); + + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, + ps_cur_au->i4_mv_buf_id, BUF_MGR_REF | BUF_MGR_IO); + + ps_view_ctxt->au1_pic_buf_ref_flag[ps_cur_au->i4_pic_buf_id] = 0; + } + + if((!ps_view_ctxt->u1_last_pic_not_decoded && + (0 == (ps_view_ctxt->ps_cur_pic->u4_pack_slc_typ & ps_view_ctxt->u4_skip_frm_mask))) || + b_is_idr) + { + ih264_buf_mgr_set_status(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, + ps_cur_au->i4_pic_buf_id, BUF_MGR_IO); + } + + if(IS_OUT_OF_RANGE_S32(i8_display_poc)) + { + ps_view_ctxt->i4_prev_max_display_seq = 0; + } + + i4_error_code = imvcd_dpb_insert_pic_in_display_list( + ps_dpb_mgr, i8_display_poc, ps_cur_au->i4_frame_num, ps_cur_au->i4_pic_buf_id); + + if(i4_error_code != OK) + { + return IV_FAIL; + } + + if(IVD_DECODE_FRAME_OUT == ps_view_ctxt->e_frm_out_mode) + { + i4_error_code = imvcd_dpb_assign_display_seq(ps_dpb_mgr); + + if(i4_error_code != OK) + { + return IV_FAIL; + } + } + + ps_view_ctxt->u4_total_frames_decoded++; + + /* In case the decoder is configured to run in low delay mode, + * then get display buffer and then format convert. + * Note in this mode, format conversion does not run paralelly in a thread + * and adds to the codec cycles + */ + if((IVD_DECODE_FRAME_OUT == ps_view_ctxt->e_frm_out_mode) && ps_view_ctxt->u1_init_dec_flag) + { + i4_error_code = imvcd_get_next_display_au_buf(ps_mvcd_ctxt); + + if(i4_error_code != OK) + { + return IV_FAIL; + } + + ps_op->s_ivd_op.u4_output_present = 1; + } + + ps_cur_au->u1_pic_type |= TOP_REF | BOT_REF; + + if(ps_view_ctxt->u4_pic_buf_got) + { + if(ps_view_ctxt->u1_last_pic_not_decoded) + { + return IV_FAIL; + } + else if(b_is_ref_au) + { + if(b_is_idr) + { + ps_dpb_mgr->u1_mmco_error_in_seq = 0; + + if(!ps_view_ctxt->ps_dpb_cmds->u1_long_term_reference_flag) + { + imvcd_reset_dpb(ps_dpb_mgr); + + i4_error_code = imvcd_dpb_insert_st_node(ps_dpb_mgr, ps_cur_au); + + if(i4_error_code != OK) + { + return IV_FAIL; + } + + ps_dpb_mgr->u1_max_lt_frame_idx = NO_LONG_TERM_INDICIES; + } + else + { + i4_error_code = imvcd_dpb_insert_st_node(ps_dpb_mgr, ps_cur_au); + + if(i4_error_code != OK) + { + return IV_FAIL; + } + + imvcd_dpb_delete_st_node_or_make_lt(ps_dpb_mgr, ps_cur_au->i4_pic_num, 0); + + ps_dpb_mgr->u1_max_lt_frame_idx = 0; + } + } + else if(!ps_dpb_mgr->u1_mmco_error_in_seq) + { + i4_error_code = imvcd_dpb_do_mmco(ps_view_ctxt->ps_dpb_cmds, ps_dpb_mgr, ps_cur_au, + ps_view_ctxt->ps_cur_sps->u1_num_ref_frames, + ps_view_ctxt->e_dec_status); + + ps_dpb_mgr->u1_mmco_error_in_seq = i4_error_code != OK; + } + + i4_error_code = imvcd_dpb_update_default_index_list(ps_dpb_mgr); + + if(i4_error_code != OK) + { + return IV_FAIL; + } + } + } + + ps_op->s_ivd_op.u4_frame_decoded_flag = 1; + + return IV_SUCCESS; +} + +/* Description - 'AU Decode' API for MVC Decoder */ +static IV_API_CALL_STATUS_T imvcd_decode(iv_obj_t *ps_dec_hdl, imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op) +{ + IV_API_CALL_STATUS_T e_retval; + + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + imvcd_video_decode_ip_t s_view_ip = ps_ip[0]; + imvcd_video_decode_op_t s_view_op = ps_op[0]; + + UWORD16 u2_num_views_decoded = 0; + UWORD16 u2_num_views = (ps_mvcd_ctxt->b_flush_enabled || ps_mvcd_ctxt->b_header_only_decode) + ? 1 + : ps_mvcd_ctxt->u2_num_views; + + ps_mvcd_ctxt->u2_num_views_decoded = 0; + + if(IV_SUCCESS != imvcd_check_dec_handle(ps_dec_hdl)) + { + return IV_FAIL; + } + + if(IV_SUCCESS != imvcd_check_decode_structs(ps_dec_hdl, ps_ip, ps_op)) + { + return IV_FAIL; + } + + if(!ps_mvcd_ctxt->b_header_only_decode) + { + if(IV_SUCCESS != imvcd_au_error_checks(ps_mvcd_ctxt, ps_ip)) + { + return IV_FAIL; + } + } + + /*Data memory barries instruction,so that bitstream write by the application + * is complete*/ + DATA_SYNC(); + + imvcd_au_init(ps_dec_hdl, ps_ip, ps_op); + + if(ps_mvcd_ctxt->b_flush_enabled) + { + return imvcd_flush_mode_decode(ps_mvcd_ctxt, ps_op); + } + + while(u2_num_views_decoded < u2_num_views) + { + e_retval = imvcd_view_decode(ps_dec_hdl, &s_view_ip, &s_view_op); + + if(IV_SUCCESS != e_retval) + { + ps_op->s_ivd_op.u4_error_code = s_view_op.s_ivd_op.u4_error_code; + + return IV_FAIL; + } + + s_view_ip.s_ivd_ip.pv_stream_buffer = ((UWORD8 *) s_view_ip.s_ivd_ip.pv_stream_buffer) + + s_view_op.s_ivd_op.u4_num_bytes_consumed; + s_view_ip.s_ivd_ip.u4_num_Bytes -= s_view_op.s_ivd_op.u4_num_bytes_consumed; + ps_op->s_ivd_op.u4_num_bytes_consumed += s_view_op.s_ivd_op.u4_num_bytes_consumed; + + u2_num_views_decoded++; + ps_mvcd_ctxt->u2_num_views_decoded++; + } + + if(!ps_mvcd_ctxt->b_header_only_decode) + { + e_retval = imvcd_finish_au_decode(ps_mvcd_ctxt, ps_op); + + if(IV_SUCCESS != e_retval) + { + return IV_FAIL; + } + } + + ps_op->s_ivd_op.u4_pic_wd = ps_view_ctxt->u2_disp_width; + ps_op->s_ivd_op.u4_pic_ht = ps_view_ctxt->u2_disp_height; + ps_op->s_ivd_op.u4_output_present = ps_view_ctxt->u4_output_present; + ps_op->s_ivd_op.u4_ts = ps_view_ctxt->s_disp_op.u4_ts; + ps_op->s_ivd_op.i4_reorder_depth = ps_view_ctxt->i4_reorder_depth; + ps_op->s_ivd_op.e_output_format = IV_YUV_420P; + + if(ps_op->s_ivd_op.u4_output_present) + { + imvcd_convert_to_app_disp_buf(ps_mvcd_ctxt, ps_op->ps_view_disp_bufs); + } + + return e_retval; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_set_dec_mode(iv_obj_t *ps_dec_hdl, + imvcd_set_config_ip_t *ps_ip, + imvcd_set_config_op_t *ps_op) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_view_ctxt->u4_skip_frm_mask = SKIP_NONE; + + ps_op->s_ivd_op.u4_error_code = 0; + + ps_view_ctxt->u4_app_disp_width = 0; + + if(ps_ip->s_ivd_ip.e_frm_skip_mode != IVD_SKIP_NONE) + { + ps_op->s_ivd_op.u4_error_code = (1 << IVD_UNSUPPORTEDPARAM); + + return IV_FAIL; + } + + if(ps_ip->s_ivd_ip.e_vid_dec_mode == IVD_DECODE_FRAME) + { + ps_view_ctxt->i4_decode_header = 0; + ps_mvcd_ctxt->b_header_only_decode = false; + } + else if(ps_ip->s_ivd_ip.e_vid_dec_mode == IVD_DECODE_HEADER) + { + ps_view_ctxt->i4_decode_header = 1; + ps_mvcd_ctxt->b_header_only_decode = true; + } + else + { + ps_op->s_ivd_op.u4_error_code = (1 << IVD_UNSUPPORTEDPARAM); + + return IV_FAIL; + } + + if((ps_ip->s_ivd_ip.e_frm_out_mode != IVD_DECODE_FRAME_OUT) && + (ps_ip->s_ivd_ip.e_frm_out_mode != IVD_DISPLAY_FRAME_OUT)) + { + ps_op->s_ivd_op.u4_error_code = (1 << IVD_UNSUPPORTEDPARAM); + + return IV_FAIL; + } + + ps_mvcd_ctxt->b_flush_enabled = false; + ps_view_ctxt->e_frm_out_mode = ps_ip->s_ivd_ip.e_frm_out_mode; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_set_num_cores(iv_obj_t *ps_dec_hdl, + imvcd_set_num_cores_ip_t *ps_ip, + imvcd_set_num_cores_op_t *ps_op) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_view_ctxt->u4_num_cores = ps_ip->u4_num_cores; + + ps_op->u4_error_code = 0; + + if(ps_view_ctxt->u4_num_cores == 1) + { + ps_view_ctxt->u1_separate_parse = 0; + } + else + { + ps_view_ctxt->u1_separate_parse = 1; + } + + /*using only upto three threads currently*/ + if(ps_view_ctxt->u4_num_cores > 3) + { + ps_view_ctxt->u4_num_cores = 3; + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_set_arch(iv_obj_t *ps_dec_hdl, imvcd_set_arch_ip_t *ps_ip, + imvcd_set_arch_op_t *ps_op) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_view_ctxt->e_processor_arch = ps_ip->e_arch; + ps_view_ctxt->e_processor_soc = ps_ip->e_soc; + + ps_op->u4_error_code = 0; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_set_degrade_mode(iv_obj_t *ps_dec_hdl, + imvcd_set_degrade_mode_ip_t *ps_ip, + imvcd_set_degrade_mode_op_t *ps_op) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_view_ctxt->i4_degrade_type = ps_ip->i4_degrade_type; + ps_view_ctxt->i4_nondegrade_interval = ps_ip->i4_nondegrade_interval; + ps_view_ctxt->i4_degrade_pics = ps_ip->i4_degrade_pics; + ps_view_ctxt->i4_degrade_pic_cnt = 0; + + ps_op->u4_error_code = 0; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_flush_dec(iv_obj_t *ps_dec_hdl, imvcd_flush_dec_ip_t *ps_ip, + imvcd_flush_dec_op_t *ps_op) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UNUSED(ps_ip); + + ps_op->s_ivd_op.u4_error_code = 0; + + ps_mvcd_ctxt->b_flush_enabled = true; + ps_view_ctxt->u1_flushfrm = 1; + + if(ps_view_ctxt->u1_init_dec_flag) + { + imvcd_release_all_ref_bufs(ps_mvcd_ctxt, ps_view_ctxt->u1_pic_bufs); + imvcd_dpb_release_display_bufs(ps_mvcd_ctxt->ps_dpb_mgr); + } + + /* Ignore dangling fields during flush */ + ps_view_ctxt->u1_top_bottom_decoded = 0; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_get_buf_info(iv_obj_t *ps_dec_hdl, + imvcd_get_buf_info_ip_t *ps_ip, + imvcd_get_buf_info_op_t *ps_op) +{ + UWORD32 au4_min_out_buf_size[IVD_VIDDEC_MAX_IO_BUFFERS]; + UWORD32 u4_pic_wd, u4_pic_ht; + UWORD32 i; + + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UNUSED(ps_ip); + + ps_op->s_ivd_op.u4_error_code = 0; + + ps_op->s_ivd_op.u4_num_disp_bufs = 0; + ps_op->s_ivd_op.u4_min_num_in_bufs = MIN_IN_BUFS; + + u4_pic_wd = 0; + u4_pic_ht = 0; + + if(is_header_decoded(ps_view_ctxt->i4_header_decoded, SPS)) + { + u4_pic_wd = ps_view_ctxt->u2_disp_width; + u4_pic_ht = ps_view_ctxt->u2_disp_height; + } + + ps_op->s_mvc_buf_info.u2_num_views = ps_mvcd_ctxt->u2_num_views; + + for(i = 0; i < ps_op->s_ivd_op.u4_min_num_in_bufs; i++) + { + ps_op->s_ivd_op.u4_min_in_buf_size[i] = + MAX(256000, u4_pic_wd * u4_pic_ht * ps_mvcd_ctxt->u2_num_views * 3 / 2); + } + + ps_op->s_ivd_op.u4_min_num_out_bufs = ih264d_get_outbuf_size( + u4_pic_wd, u4_pic_ht, ps_view_ctxt->u1_chroma_format, &au4_min_out_buf_size[0]); + ps_op->s_ivd_op.u4_min_num_out_bufs *= ps_mvcd_ctxt->u2_num_views; + + for(i = 0; i < ps_op->s_ivd_op.u4_min_num_out_bufs; i++) + { + ps_op->s_ivd_op.u4_min_out_buf_size[i] = au4_min_out_buf_size[i % NUM_COMPONENTS]; + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_ctl_get_vui(iv_obj_t *ps_dec_hdl, imvcd_get_vui_ip_t *ps_ip, + imvcd_get_vui_op_t *ps_op) +{ + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UNUSED(ps_ip); + + ps_op->u4_error_code = 0; + ps_op->b_is_vui_available = false; + + if((ps_mvcd_ctxt->u1_num_sps > 0) && ps_view_ctxt->ps_cur_sps) + { + ps_op->b_is_vui_available = ps_view_ctxt->ps_cur_sps->u1_vui_parameters_present_flag; + + if(ps_op->b_is_vui_available) + { + ps_op->u1_aspect_ratio_idc = ps_view_ctxt->ps_cur_sps->s_vui.u1_aspect_ratio_idc; + ps_op->u2_sar_width = ps_view_ctxt->ps_cur_sps->s_vui.u2_sar_width; + ps_op->u2_sar_height = ps_view_ctxt->ps_cur_sps->s_vui.u2_sar_height; + ps_op->u1_overscan_appropriate_flag = + ps_view_ctxt->ps_cur_sps->s_vui.u1_overscan_appropriate_flag; + ps_op->u1_video_format = ps_view_ctxt->ps_cur_sps->s_vui.u1_video_format; + ps_op->u1_video_full_range_flag = + ps_view_ctxt->ps_cur_sps->s_vui.u1_video_full_range_flag; + ps_op->u1_colour_primaries = ps_view_ctxt->ps_cur_sps->s_vui.u1_colour_primaries; + ps_op->u1_tfr_chars = ps_view_ctxt->ps_cur_sps->s_vui.u1_tfr_chars; + ps_op->u1_matrix_coeffs = ps_view_ctxt->ps_cur_sps->s_vui.u1_matrix_coeffs; + ps_op->u1_cr_top_field = ps_view_ctxt->ps_cur_sps->s_vui.u1_cr_top_field; + ps_op->u1_cr_bottom_field = ps_view_ctxt->ps_cur_sps->s_vui.u1_cr_bottom_field; + ps_op->u4_num_units_in_tick = ps_view_ctxt->ps_cur_sps->s_vui.u4_num_units_in_tick; + ps_op->u4_time_scale = ps_view_ctxt->ps_cur_sps->s_vui.u4_time_scale; + ps_op->u1_fixed_frame_rate_flag = + ps_view_ctxt->ps_cur_sps->s_vui.u1_fixed_frame_rate_flag; + ps_op->u1_nal_hrd_params_present = + ps_view_ctxt->ps_cur_sps->s_vui.u1_nal_hrd_params_present; + ps_op->u1_vcl_hrd_params_present = + ps_view_ctxt->ps_cur_sps->s_vui.u1_vcl_hrd_params_present; + ps_op->u1_low_delay_hrd_flag = ps_view_ctxt->ps_cur_sps->s_vui.u1_low_delay_hrd_flag; + ps_op->u1_pic_struct_present_flag = + ps_view_ctxt->ps_cur_sps->s_vui.u1_pic_struct_present_flag; + ps_op->u1_bitstream_restriction_flag = + ps_view_ctxt->ps_cur_sps->s_vui.u1_bitstream_restriction_flag; + ps_op->u1_mv_over_pic_boundaries_flag = + ps_view_ctxt->ps_cur_sps->s_vui.u1_mv_over_pic_boundaries_flag; + ps_op->u4_max_bytes_per_pic_denom = + ps_view_ctxt->ps_cur_sps->s_vui.u4_max_bytes_per_pic_denom; + ps_op->u4_max_bits_per_mb_denom = + ps_view_ctxt->ps_cur_sps->s_vui.u4_max_bits_per_mb_denom; + ps_op->u4_log2_max_mv_length_horz = + ps_view_ctxt->ps_cur_sps->s_vui.u4_log2_max_mv_length_horz; + ps_op->u4_log2_max_mv_length_vert = + ps_view_ctxt->ps_cur_sps->s_vui.u4_log2_max_mv_length_vert; + ps_op->u4_num_reorder_frames = ps_view_ctxt->ps_cur_sps->s_vui.u4_num_reorder_frames; + ps_op->u4_max_dec_frame_buffering = + ps_view_ctxt->ps_cur_sps->s_vui.u4_max_dec_frame_buffering; + } + } + + return IV_SUCCESS; +} + +/* Description - 'Control Cmd' API for MVC Decoder */ +static IV_API_CALL_STATUS_T imvcd_ctl_cmd_handler(iv_obj_t *ps_dec_hdl, void *pv_ip, void *pv_op) +{ + ivd_ctl_set_config_ip_t *ps_ip = (ivd_ctl_set_config_ip_t *) pv_ip; + + WORD32 i4_sub_cmd = ps_ip->e_sub_cmd; + + if(IV_SUCCESS != imvcd_check_dec_handle(ps_dec_hdl)) + { + return IV_FAIL; + } + + if(IV_SUCCESS != imvcd_check_ctl_structs(pv_ip, pv_op)) + { + return IV_FAIL; + } + + switch(i4_sub_cmd) + { + case IVD_CMD_CTL_SETPARAMS: + { + return imvcd_ctl_set_dec_mode(ps_dec_hdl, pv_ip, pv_op); + } + case IMVCD_CTL_SET_NUM_CORES: + { + return imvcd_ctl_set_num_cores(ps_dec_hdl, pv_ip, pv_op); + } + case IMVCD_CTL_SET_PROCESSOR: + { + return imvcd_ctl_set_arch(ps_dec_hdl, pv_ip, pv_op); + } + case IMVCD_CTL_DEGRADE: + { + return imvcd_ctl_set_degrade_mode(ps_dec_hdl, pv_ip, pv_op); + } + case IVD_CMD_CTL_FLUSH: + { + return imvcd_ctl_flush_dec(ps_dec_hdl, pv_ip, pv_op); + } + case IVD_CMD_CTL_GETBUFINFO: + { + return imvcd_ctl_get_buf_info(ps_dec_hdl, pv_ip, pv_op); + } + case IMVCD_CTL_GET_VUI_PARAMS: + { + return imvcd_ctl_get_vui(ps_dec_hdl, pv_ip, pv_op); + } + default: + { + return IV_FAIL; + } + } +} + +IV_API_CALL_STATUS_T imvcd_api_function(iv_obj_t *ps_dec_hdl, void *pv_ip, void *pv_op) +{ + IVD_API_COMMAND_TYPE_T e_cmd = ((WORD32 *) pv_ip)[1]; + + switch(e_cmd) + { + case IVD_CMD_CREATE: + { + return imvcd_create(pv_ip, pv_op); + } + case IVD_CMD_DELETE: + { + return imvcd_delete(ps_dec_hdl); + } + case IVD_CMD_VIDEO_CTL: + { + return imvcd_ctl_cmd_handler(ps_dec_hdl, pv_ip, pv_op); + } + case IVD_CMD_VIDEO_DECODE: + { + return imvcd_decode(ps_dec_hdl, pv_ip, pv_op); + } + default: + { + return IV_FAIL; + } + } +} diff --git a/decoder/mvc/imvcd_api_utils.c b/decoder/mvc/imvcd_api_utils.c new file mode 100644 index 0000000..1f2b269 --- /dev/null +++ b/decoder/mvc/imvcd_api_utils.c @@ -0,0 +1,392 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_api_utils.c */ +/* */ +/* Description : Utility functions used by 'imvcd_api.c' */ +/* */ +/*****************************************************************************/ +#include + +#include "ih264_typedefs.h" +#include "iv.h" +#include "imvcd.h" +#include "ih264_disp_mgr.h" +#include "ih264d_structs.h" +#include "ih264d_tables.h" +#include "ih264d_utils.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +IV_API_CALL_STATUS_T imvcd_check_dec_handle(iv_obj_t *ps_handle) +{ + if(ps_handle == NULL) + { + return IV_FAIL; + } + + if(ps_handle->pv_codec_handle == NULL) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} + +IV_API_CALL_STATUS_T imvcd_check_create_structs(imvcd_create_ip_t *ps_ip, imvcd_create_op_t *ps_op) +{ + if(NULL == ps_ip) + { + return IV_FAIL; + } + + if(NULL == ps_op) + { + return IV_FAIL; + } + + if(ps_ip->s_ivd_ip.e_output_format != IV_YUV_420P) + { + return IV_FAIL; + } + + if(NULL == ps_ip->s_ivd_ip.pf_aligned_alloc) + { + return IV_FAIL; + } + + if(NULL == ps_ip->s_ivd_ip.pf_aligned_free) + { + return IV_FAIL; + } + + if(0 != ps_ip->s_ivd_ip.u4_share_disp_buf) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} + +IV_API_CALL_STATUS_T imvcd_check_ctl_structs(void *pv_ip, void *pv_op) +{ + ivd_ctl_set_config_ip_t *ps_ip = (ivd_ctl_set_config_ip_t *) pv_ip; + ivd_ctl_set_config_op_t *ps_op = (ivd_ctl_set_config_op_t *) pv_op; + + WORD32 i4_sub_cmd = ps_ip->e_sub_cmd; + + if(NULL == ps_ip) + { + return IV_FAIL; + } + + if(NULL == ps_op) + { + return IV_FAIL; + } + + switch(i4_sub_cmd) + { + case IVD_CMD_CTL_SETPARAMS: + { + if((ps_ip->u4_size != sizeof(ivd_ctl_set_config_ip_t)) || + (ps_op->u4_size != sizeof(ivd_ctl_set_config_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + case IMVCD_CTL_SET_NUM_CORES: + { + if((ps_ip->u4_size != sizeof(imvcd_set_num_cores_ip_t)) || + (ps_op->u4_size != sizeof(imvcd_set_num_cores_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + case IMVCD_CTL_SET_PROCESSOR: + { + if((ps_ip->u4_size != sizeof(imvcd_set_arch_ip_t)) || + (ps_op->u4_size != sizeof(imvcd_set_arch_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + case IMVCD_CTL_DEGRADE: + { + if((ps_ip->u4_size != sizeof(imvcd_set_degrade_mode_ip_t)) || + (ps_op->u4_size != sizeof(imvcd_set_degrade_mode_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + case IVD_CMD_CTL_FLUSH: + { + if((ps_ip->u4_size != sizeof(ivd_ctl_flush_ip_t)) || + (ps_op->u4_size != sizeof(ivd_ctl_flush_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + case IVD_CMD_CTL_GETBUFINFO: + { + if((ps_ip->u4_size != sizeof(ivd_ctl_getbufinfo_ip_t)) || + (ps_op->u4_size != sizeof(ivd_ctl_getbufinfo_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + case IMVCD_CTL_GET_VUI_PARAMS: + { + if((ps_ip->u4_size != sizeof(imvcd_get_vui_ip_t)) || + (ps_op->u4_size != sizeof(imvcd_get_vui_op_t))) + { + return IV_FAIL; + } + else + { + return IV_SUCCESS; + } + } + default: + { + return IV_FAIL; + } + } +} + +IV_API_CALL_STATUS_T imvcd_check_decode_structs(iv_obj_t *ps_dec_hdl, + imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op) +{ + WORD32 i, j; + + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + + UWORD16 u2_num_views = 1; + + if(NULL == ps_ip) + { + return IV_FAIL; + } + + if(NULL == ps_op) + { + return IV_FAIL; + } + + if(!ps_mvcd_ctxt->b_flush_enabled && !ps_mvcd_ctxt->b_header_only_decode) + { + if(NULL == ps_ip->s_ivd_ip.pv_stream_buffer) + { + return IV_FAIL; + } + + for(i = 0; i < u2_num_views; i++) + { + for(j = 0; j < NUM_COMPONENTS; j++) + { + if(NULL == ps_ip->s_ivd_ip.s_out_buffer.pu1_bufs[i * NUM_COMPONENTS + j]) + { + return IV_FAIL; + } + } + } + + if(0 == ps_ip->s_ivd_ip.u4_num_Bytes) + { + return IV_FAIL; + } + } + + return IV_SUCCESS; +} + +static void imvcd_convert_app_out_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt, + ivd_out_bufdesc_t *ps_app_buffer) +{ + if(!ps_mvcd_ctxt->b_header_only_decode) + { + WORD32 i, j; + + subset_sps_t *ps_subset_sps = imvcd_get_valid_subset_sps(ps_mvcd_ctxt); + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UWORD16 u2_num_views = + (NULL == ps_subset_sps) ? 1 : ps_subset_sps->s_sps_mvc_ext.u2_num_views; + + for(i = 0; i < u2_num_views; i++) + { + yuv_buf_props_t *ps_view_buf = &ps_mvcd_ctxt->s_out_buffer.as_view_buf_props[i]; + + ps_view_buf->u1_bit_depth = 8; + ps_view_buf->u2_height = ps_view_ctxt->u2_disp_height; + ps_view_buf->u2_width = ps_view_ctxt->u2_disp_width; + + for(j = 0; j < NUM_COMPONENTS; j++) + { + buffer_container_t *ps_component_buf = &ps_view_buf->as_component_bufs[j]; + bool b_is_chroma = (((COMPONENT_TYPES_T) j) != Y); + + ps_component_buf->pv_data = ps_app_buffer->pu1_bufs[i * NUM_COMPONENTS + j]; + ps_component_buf->i4_data_stride = ps_view_buf->u2_width >> b_is_chroma; + } + } + } +} + +void imvcd_convert_to_app_disp_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt, iv_yuv_buf_t *ps_view_disp_bufs) +{ + WORD32 i; + + UWORD16 u2_num_views = ps_mvcd_ctxt->u2_num_views; + + for(i = 0; i < u2_num_views; i++) + { + yuv_buf_props_t *ps_view_buf = &ps_mvcd_ctxt->s_out_buffer.as_view_buf_props[i]; + + ps_view_disp_bufs[i].u4_size = sizeof(ps_view_disp_bufs[i]); + + ps_view_disp_bufs[i].pv_y_buf = ps_view_buf->as_component_bufs[Y].pv_data; + ps_view_disp_bufs[i].u4_y_strd = ps_view_buf->as_component_bufs[Y].i4_data_stride; + ps_view_disp_bufs[i].u4_y_wd = ps_view_buf->u2_width; + ps_view_disp_bufs[i].u4_y_ht = ps_view_buf->u2_height; + + ps_view_disp_bufs[i].pv_u_buf = ps_view_buf->as_component_bufs[U].pv_data; + ps_view_disp_bufs[i].u4_u_strd = ps_view_buf->as_component_bufs[U].i4_data_stride; + ps_view_disp_bufs[i].u4_u_wd = ps_view_buf->u2_width / 2; + ps_view_disp_bufs[i].u4_u_ht = ps_view_buf->u2_height / 2; + + ps_view_disp_bufs[i].pv_v_buf = ps_view_buf->as_component_bufs[V].pv_data; + ps_view_disp_bufs[i].u4_v_strd = ps_view_buf->as_component_bufs[V].i4_data_stride; + ps_view_disp_bufs[i].u4_v_wd = ps_view_buf->u2_width / 2; + ps_view_disp_bufs[i].u4_v_ht = ps_view_buf->u2_height / 2; + } +} + +void imvcd_au_init(iv_obj_t *ps_dec_hdl, imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op) +{ + subset_sps_t *ps_subset_sps; + + mvc_dec_ctxt_t *ps_mvcd_ctxt = (mvc_dec_ctxt_t *) ps_dec_hdl->pv_codec_handle; + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_mvcd_ctxt->u2_num_views_decoded = 0; + ps_subset_sps = imvcd_get_valid_subset_sps(ps_mvcd_ctxt); + ps_mvcd_ctxt->u2_num_views = + (NULL == ps_subset_sps) ? 1 : ps_subset_sps->s_sps_mvc_ext.u2_num_views; + imvcd_convert_app_out_buf(ps_mvcd_ctxt, &ps_ip->s_ivd_ip.s_out_buffer); + + ps_op->s_ivd_op.u4_num_bytes_consumed = 0; + ps_op->s_ivd_op.u4_output_present = 0; + ps_op->s_ivd_op.u4_error_code = 0; + ps_op->s_ivd_op.e_pic_type = IV_FRAMETYPE_DEFAULT; + ps_op->s_ivd_op.u4_frame_decoded_flag = 0; + ps_op->s_ivd_op.u4_new_seq = 0; + ps_op->s_ivd_op.u4_progressive_frame_flag = 1; + ps_op->s_ivd_op.u4_is_ref_flag = 1; + ps_op->s_ivd_op.e4_fld_type = IV_NA_FLD; + + ps_view_ctxt->u4_fmt_conv_cur_row = 0; + ps_view_ctxt->u4_output_present = 0; + ps_view_ctxt->u4_fmt_conv_num_rows = FMT_CONV_NUM_ROWS; + ps_view_ctxt->u4_ts = ps_ip->s_ivd_ip.u4_ts; + ps_view_ctxt->i4_frametype = IV_NA_FRAME; + ps_view_ctxt->i4_content_type = IV_CONTENTTYPE_NA; + + /* Mimicking the hack in lines '2005' in 'ih264d_api.c' and '1323' in + * 'ih264d_parse_headers.c */ + ps_view_ctxt->u4_sps_cnt_in_process = 0; + + memset(ps_mvcd_ctxt->as_nalu_mvc_ext, 0, sizeof(ps_mvcd_ctxt->as_nalu_mvc_ext)); +} + +void imvcd_view_init(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_view_ctxt->u4_num_fld_in_frm = 0; + ps_view_ctxt->u4_slice_start_code_found = 0; + ps_view_ctxt->u2_cur_mb_addr = 0; + ps_view_ctxt->u2_total_mbs_coded = 0; + ps_view_ctxt->u2_cur_slice_num = 0; + ps_view_ctxt->cur_dec_mb_num = 0; + ps_view_ctxt->cur_recon_mb_num = 0; + ps_view_ctxt->u4_first_slice_in_pic = 1; + ps_view_ctxt->u1_slice_header_done = 0; + ps_view_ctxt->u1_dangling_field = 0; + ps_view_ctxt->u4_dec_thread_created = 0; + ps_view_ctxt->u4_bs_deblk_thread_created = 0; + ps_view_ctxt->u4_cur_bs_mb_num = 0; + ps_view_ctxt->u4_start_recon_deblk = 0; + ps_view_ctxt->u4_pic_buf_got = 0; + ps_view_ctxt->pu1_inv_scan = (UWORD8 *) gau1_ih264d_inv_scan; + ps_view_ctxt->u1_pic_decode_done = 0; + + ps_view_ctxt->pu1_init_dpb_base = NULL; + ps_view_ctxt->ps_dpb_mgr = NULL; +} + +IV_API_CALL_STATUS_T imvcd_bitstream_buf_alloc(dec_struct_t *ps_view_ctxt, UWORD16 u2_num_views) +{ + UWORD32 u4_size; + + u4_size = ((ps_view_ctxt->u2_pic_wd * ps_view_ctxt->u2_pic_ht * 3 / 2) + EXTRA_BS_OFFSET) * + u2_num_views * sizeof(ps_view_ctxt->pu1_bits_buf_dynamic[0]); + ps_view_ctxt->pu1_bits_buf_dynamic = + ps_view_ctxt->pf_aligned_alloc(ps_view_ctxt->pv_mem_ctxt, 128, u4_size); + RETURN_IF((NULL == ps_view_ctxt->pu1_bits_buf_dynamic), IV_FAIL); + + memset(ps_view_ctxt->pu1_bits_buf_dynamic, 0, u4_size); + ps_view_ctxt->u4_dynamic_bits_buf_size = u4_size; + + return IV_SUCCESS; +} + +void imvcd_bitsteam_buf_free(dec_struct_t *ps_view_ctxt) +{ + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_bits_buf_dynamic); +} diff --git a/decoder/mvc/imvcd_api_utils.h b/decoder/mvc/imvcd_api_utils.h new file mode 100644 index 0000000..0707f45 --- /dev/null +++ b/decoder/mvc/imvcd_api_utils.h @@ -0,0 +1,58 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ +/*****************************************************************************/ +/* */ +/* File Name : imvcd_api_utils.h */ +/* */ +/* Description : Utility functions used by 'imvcd_api.c' */ +/* */ +/*****************************************************************************/ + +#ifndef _IMVCD_API_UTILS_H_ +#define _IMVCD_API_UTILS_H_ + +#include "iv.h" +#include "ih264d_structs.h" +#include "imvcd_structs.h" + +extern IV_API_CALL_STATUS_T imvcd_check_dec_handle(iv_obj_t *ps_handle); + +extern IV_API_CALL_STATUS_T imvcd_check_create_structs(imvcd_create_ip_t *ps_ip, + imvcd_create_op_t *ps_op); + +extern IV_API_CALL_STATUS_T imvcd_check_ctl_structs(void *pv_ip, void *pv_op); + +extern IV_API_CALL_STATUS_T imvcd_check_decode_structs(iv_obj_t *ps_dec_hdl, + imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op); + +extern void imvcd_au_init(iv_obj_t *ps_dec_hdl, imvcd_video_decode_ip_t *ps_ip, + imvcd_video_decode_op_t *ps_op); + +extern void imvcd_view_init(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern IV_API_CALL_STATUS_T imvcd_bitstream_buf_alloc(dec_struct_t *ps_view_ctxt, + UWORD16 u2_num_views); + +extern void imvcd_bitsteam_buf_free(dec_struct_t *ps_view_ctxt); + +extern void imvcd_convert_to_app_disp_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt, + iv_yuv_buf_t *ps_view_disp_bufs); +#endif diff --git a/decoder/mvc/imvcd_defs.h b/decoder/mvc/imvcd_defs.h new file mode 100644 index 0000000..aa416bb --- /dev/null +++ b/decoder/mvc/imvcd_defs.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#ifndef _IMVCD_DEFS_H_ +#define _IMVCD_DEFS_H_ + +#include + +#include "ih264_typedefs.h" +#include "imvc_defs.h" +#include "ih264d_defs.h" + +#define MVC_MAX_REF_PICS MAX(16 * LOG2_MAX_NUM_VIEWS, 2 * H264_MAX_REF_PICS) + +/* Set to identify between actual ref pic with valid u1_pic_buf_id + and replicated IVP ref pic! Ensure that MAX_VAL_PIC_BUF_ID-MAX_NUM_VIEWS + is still greater than any possible value of u1_pic_buf_id */ +#define IVP_PIC_BUF_ID UINT8_MAX + +#endif diff --git a/decoder/mvc/imvcd_dpb_manager.c b/decoder/mvc/imvcd_dpb_manager.c new file mode 100644 index 0000000..7a88d67 --- /dev/null +++ b/decoder/mvc/imvcd_dpb_manager.c @@ -0,0 +1,2136 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_nalu_parser.h */ +/* */ +/* Description : Functions for MVC NALU parsing */ +/* */ +/*****************************************************************************/ + +#include "ih264_typedefs.h" +#include "ih264d_error_handler.h" +#include "imvcd_dpb_manager.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +void imvcd_dpb_set_display_num(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_display_num) +{ + ps_dpb_mgr->i4_cur_display_seq = i4_display_num; +} + +void imvcd_dpb_set_max_pic_num(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_max_pic_num) +{ + ps_dpb_mgr->i4_max_pic_num = i4_max_pic_num; +} + +void imvcd_dpb_set_num_views(mvc_dpb_manager_t *ps_dpb_mgr, UWORD16 u2_num_views) +{ + ps_dpb_mgr->u2_num_views = u2_num_views; +} + +void imvcd_dpb_set_display_delay(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_display_delay) +{ + ps_dpb_mgr->i4_display_delay = i4_display_delay; +} + +void imvcd_dpb_init_au_bufs(mvc_dpb_manager_t *ps_dpb_mgr, mvc_au_buffer_t *ps_cur_au) +{ + WORD32 i; + + for(i = 0; i < 2; i++) + { + ps_dpb_mgr->as_init_dpb[i][0] = ps_cur_au[0]; + } +} + +void imvcd_dpb_init_view_bufs(mvc_dpb_manager_t *ps_dpb_mgr, UWORD16 u2_view_order_id, + UWORD16 u2_view_id) +{ + WORD32 i; + + for(i = 0; i < 2; i++) + { + imvcd_convert_au_buf_to_view_buf(&ps_dpb_mgr->as_init_dpb[i][0], + &ps_dpb_mgr->as_view_init_dpb[i][0], u2_view_order_id, + u2_view_id); + } +} + +void imvcd_dpb_init_ivp_ctxt(mvc_dpb_manager_t *ps_dpb_mgr, sps_mvc_ext_t *ps_sps_mvc_ext, + nalu_mvc_ext_t *ps_nalu_mvc_exts) +{ + ps_dpb_mgr->s_dpb_ivp_ctxt.ps_nalu_mvc_exts = ps_nalu_mvc_exts; + ps_dpb_mgr->s_dpb_ivp_ctxt.ps_sps_mvc_ext = ps_sps_mvc_ext; + + ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs = 0; +} + +void imvcd_dpb_reset_ivp_ctxt(mvc_dpb_manager_t *ps_dpb_mgr) +{ + UWORD32 i; + + for(i = 0; i < ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs; i++) + { + ih264_buf_mgr_release(ps_dpb_mgr->ps_mvc_au_buf_mgr->ps_buf_mgr_ctxt, + ps_dpb_mgr->s_dpb_ivp_ctxt.au1_au_buf_ids[i], + BUF_MGR_REF | BUF_MGR_IO); + + ih264_buf_mgr_release(ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr->ps_buf_mgr_ctxt, + ps_dpb_mgr->s_dpb_ivp_ctxt.au1_mv_buf_ids[i], + BUF_MGR_REF | BUF_MGR_IO); + } + + ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs = 0; +} + +pic_buffer_t **imvcd_dpb_get_view_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, + UWORD16 u2_view_order_id, UWORD16 u2_view_id, + UWORD8 u1_pred_dir) +{ + WORD32 i; + + UWORD8 u1_num_ref_bufs = ps_dpb_mgr->au1_num_active_st_refs[u1_pred_dir] + + ps_dpb_mgr->au1_num_active_lt_refs[u1_pred_dir]; + + for(i = 0; i < u1_num_ref_bufs; i++) + { + imvcd_convert_au_buf_to_view_buf(ps_dpb_mgr->aps_mod_dpb[u1_pred_dir][i], + &ps_dpb_mgr->as_view_init_dpb[u1_pred_dir][i], + u2_view_order_id, u2_view_id); + + ps_dpb_mgr->aps_view_mod_dpb[u1_pred_dir][i] = + &ps_dpb_mgr->as_view_init_dpb[u1_pred_dir][i]; + } + + return ps_dpb_mgr->aps_view_mod_dpb[u1_pred_dir]; +} + +void imvcd_init_dpb_mgr(mvc_dpb_manager_t *ps_dpb_mgr, mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr, + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr, + disp_mgr_t *ps_disp_buf_mgr) +{ + WORD32 i, j, k, l; + + mvc_dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info; + + for(i = 0; i < 2; i++) + { + mvc_au_buffer_t *ps_init_dpb = ps_dpb_mgr->as_init_dpb[i]; + pic_buffer_t *ps_view_init_dpb = ps_dpb_mgr->as_view_init_dpb[i]; + + for(j = 0; j < MVC_MAX_REF_PICS; j++) + { + for(k = 0; k < MAX_NUM_VIEWS; k++) + { + for(l = 0; l < NUM_COMPONENTS; l++) + { + ps_init_dpb->as_view_buffers[k].as_component_bufs[l].pv_data = NULL; + } + } + + ps_view_init_dpb->pu1_buf1 = NULL; + ps_view_init_dpb->pu1_buf2 = NULL; + ps_view_init_dpb->pu1_buf3 = NULL; + + ps_dpb_mgr->aps_mod_dpb[i][j] = ps_init_dpb; + ps_dpb_mgr->aps_view_mod_dpb[i][j] = ps_view_init_dpb; + + ps_init_dpb++; + ps_view_init_dpb++; + } + } + + for(i = 0; i < MVC_MAX_REF_PICS; i++) + { + ps_dpb_info[i].b_used_as_ref = false; + ps_dpb_info[i].ps_prev_short = NULL; + ps_dpb_info[i].ps_prev_long = NULL; + ps_dpb_info[i].ps_au_buf = NULL; + ps_dpb_info[i].s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_dpb_info[i].s_bot_field.u1_reference_info = UNUSED_FOR_REF; + ps_dpb_info[i].s_top_field.u1_long_term_frame_idx = MVC_MAX_REF_PICS + 1; + ps_dpb_info[i].s_bot_field.u1_long_term_frame_idx = MVC_MAX_REF_PICS + 1; + } + + ps_dpb_mgr->u1_num_st_ref_bufs = ps_dpb_mgr->u1_num_lt_ref_bufs = 0; + ps_dpb_mgr->ps_dpb_st_head = NULL; + ps_dpb_mgr->ps_dpb_lt_head = NULL; + ps_dpb_mgr->i1_gaps_deleted = 0; + ps_dpb_mgr->i1_poc_buf_id_entries = 0; + ps_dpb_mgr->u1_mmco_error_in_seq = 0; + ps_dpb_mgr->u1_num_gaps = 0; + ps_dpb_mgr->i4_display_delay = 0; + ps_dpb_mgr->i4_cur_display_seq = 0; + + for(i = 0; i < MAX_FRAMES; i++) + { + ps_dpb_mgr->ai4_gaps_start_frm_num[i] = INVALID_FRAME_NUM; + ps_dpb_mgr->ai4_gaps_end_frm_num[i] = 0; + ps_dpb_mgr->ai1_gaps_per_seq[i] = 0; + ps_dpb_mgr->as_display_buf_info[i].i4_poc_buf_id = -1; + ps_dpb_mgr->as_display_buf_info[i].i4_poc = INT32_MAX; + ps_dpb_mgr->as_display_buf_info[i].i4_frame_num = 0; + } + + ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs = 0; + ps_dpb_mgr->s_dpb_ivp_ctxt.ps_nalu_mvc_exts = NULL; + ps_dpb_mgr->s_dpb_ivp_ctxt.ps_sps_mvc_ext = NULL; + + ps_dpb_mgr->ps_mvc_au_buf_mgr = ps_mvc_au_buf_mgr; + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr = ps_mvc_au_mv_pred_buf_mgr; + ps_dpb_mgr->ps_disp_buf_mgr = ps_disp_buf_mgr; +} + +WORD32 imvcd_dpb_assign_display_seq(mvc_dpb_manager_t *ps_dpb_mgr) +{ + WORD32 i; + + display_buf_info_t *ps_display_buf_info = ps_dpb_mgr->as_display_buf_info; + + WORD32 i4_min_poc = INT32_MAX; + WORD32 i4_min_poc_buf_id = -1; + WORD32 i4_min_index = -1; + + if(ps_dpb_mgr->i1_poc_buf_id_entries >= ps_dpb_mgr->i4_display_delay) + { + for(i = 0; i < MAX_FRAMES; i++) + { + if((-1 != ps_display_buf_info[i].i4_poc_buf_id) && + (DO_NOT_DISP != ps_display_buf_info[i].i4_poc_buf_id)) + { + /* Checking for <= is necessary to handle cases where there is one + valid buffer with poc set to 0x7FFFFFFF. */ + if(ps_display_buf_info[i].i4_poc <= i4_min_poc) + { + i4_min_poc = ps_display_buf_info[i].i4_poc; + i4_min_poc_buf_id = ps_display_buf_info[i].i4_poc_buf_id; + i4_min_index = i; + } + } + } + + if((i4_min_index != -1) && (DO_NOT_DISP != i4_min_poc_buf_id)) + { + ps_dpb_mgr->i4_cur_display_seq++; + + ih264_disp_mgr_add( + ps_dpb_mgr->ps_disp_buf_mgr, i4_min_poc_buf_id, ps_dpb_mgr->i4_cur_display_seq, + ps_dpb_mgr->ps_mvc_au_buf_mgr->aps_buf_id_to_au_buf_map[i4_min_poc_buf_id]); + + ps_display_buf_info[i4_min_index].i4_poc_buf_id = -1; + ps_display_buf_info[i4_min_index].i4_poc = 0x7fffffff; + + ps_dpb_mgr->i1_poc_buf_id_entries--; + } + else if(DO_NOT_DISP == i4_min_poc_buf_id) + { + return ERROR_GAPS_IN_FRM_NUM; + } + } + + return OK; +} + +WORD32 imvcd_dpb_insert_pic_in_display_list(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_display_poc, + UWORD32 u4_frame_num, WORD32 i4_buf_id) +{ + WORD32 i; + + display_buf_info_t *ps_display_buf_info = ps_dpb_mgr->as_display_buf_info; + + for(i = 0; i < MAX_FRAMES; i++) + { + /* Find an empty slot */ + if(ps_display_buf_info[i].i4_poc_buf_id == -1) + { + if(GAP_FRAME_NUM == ps_display_buf_info[i].i4_frame_num) + { + ps_dpb_mgr->i1_gaps_deleted--; + } + else + { + ps_dpb_mgr->i1_poc_buf_id_entries++; + } + + ps_display_buf_info[i].i4_poc_buf_id = i4_buf_id; + ps_display_buf_info[i].i4_poc = i4_display_poc; + ps_display_buf_info[i].i4_frame_num = u4_frame_num; + + break; + } + } + + if(MAX_FRAMES == i) + { + return ERROR_GAPS_IN_FRM_NUM; + } + + return OK; +} + +static WORD32 imvcd_dpb_delete_gap_frm_sliding(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_pic_num, + UWORD8 *pu1_del_node) +{ + WORD32 i, j, j_min; + WORD8 i1_gap_idx; + WORD32 *pi4_gaps_start_frm_num, *pi4_gaps_end_frm_num, i4_gap_frame_num; + WORD32 i4_start_frm_num, i4_end_frm_num; + WORD32 i4_max_pic_num; + WORD32 i4_frm_num, i4_gap_frm_num_min; + + /* find the least frame num from gaps and current DPB node */ + /* Delete the least one */ + *pu1_del_node = 1; + + if(0 == ps_dpb_mgr->u1_num_gaps) + { + return OK; + } + + pi4_gaps_start_frm_num = ps_dpb_mgr->ai4_gaps_start_frm_num; + pi4_gaps_end_frm_num = ps_dpb_mgr->ai4_gaps_end_frm_num; + i4_gap_frame_num = INVALID_FRAME_NUM; + i4_max_pic_num = ps_dpb_mgr->i4_max_pic_num; + + i1_gap_idx = -1; + + if(INVALID_FRAME_NUM != i4_pic_num) + { + i4_gap_frame_num = i4_pic_num; + + for(i = 0; i < MAX_FRAMES; i++) + { + i4_start_frm_num = pi4_gaps_start_frm_num[i]; + + if(INVALID_FRAME_NUM != i4_start_frm_num) + { + i4_end_frm_num = pi4_gaps_end_frm_num[i]; + + if(i4_end_frm_num < i4_max_pic_num) + { + if(i4_start_frm_num <= i4_gap_frame_num) + { + i4_gap_frame_num = i4_start_frm_num; + i1_gap_idx = i; + } + } + else + { + if(((i4_start_frm_num <= i4_gap_frame_num) && + (i4_gap_frame_num <= i4_max_pic_num)) || + ((i4_start_frm_num >= i4_gap_frame_num) && + ((i4_gap_frame_num + i4_max_pic_num) >= i4_end_frm_num))) + { + i4_gap_frame_num = i4_start_frm_num; + i1_gap_idx = i; + } + } + } + } + } + else + { + /* no valid short term buffers, delete one gap from the least start */ + /* of gap sequence */ + i4_gap_frame_num = pi4_gaps_start_frm_num[0]; + i1_gap_idx = 0; + + for(i = 1; i < MAX_FRAMES; i++) + { + if(INVALID_FRAME_NUM != pi4_gaps_start_frm_num[i]) + { + if(pi4_gaps_start_frm_num[i] < i4_gap_frame_num) + { + i4_gap_frame_num = pi4_gaps_start_frm_num[i]; + i1_gap_idx = i; + } + } + } + if(INVALID_FRAME_NUM == i4_gap_frame_num) + { + return ERROR_DBP_MANAGER_T; + } + } + + if(-1 != i1_gap_idx) + { + /* find least frame_num in the poc_map, which is in this range */ + i4_start_frm_num = pi4_gaps_start_frm_num[i1_gap_idx]; + + if(i4_start_frm_num < 0) + { + i4_start_frm_num += i4_max_pic_num; + } + + i4_end_frm_num = pi4_gaps_end_frm_num[i1_gap_idx]; + + if(i4_end_frm_num < 0) + { + i4_end_frm_num += i4_max_pic_num; + } + + i4_gap_frm_num_min = INT32_MIN; + j_min = MAX_FRAMES; + + for(j = 0; j < MAX_FRAMES; j++) + { + i4_frm_num = ps_dpb_mgr->as_display_buf_info[j].i4_frame_num; + + if((i4_start_frm_num <= i4_frm_num) && (i4_end_frm_num >= i4_frm_num)) + { + if(i4_frm_num < i4_gap_frm_num_min) + { + j_min = j; + i4_gap_frm_num_min = i4_frm_num; + } + } + } + + if(j_min != MAX_FRAMES) + { + ps_dpb_mgr->as_display_buf_info[j_min].i4_poc_buf_id = -1; + ps_dpb_mgr->as_display_buf_info[j_min].i4_poc = 0x7fffffff; + ps_dpb_mgr->as_display_buf_info[j_min].i4_frame_num = GAP_FRAME_NUM; + + ps_dpb_mgr->i1_gaps_deleted++; + ps_dpb_mgr->ai1_gaps_per_seq[i1_gap_idx]--; + ps_dpb_mgr->u1_num_gaps--; + *pu1_del_node = 0; + + if(0 == ps_dpb_mgr->ai1_gaps_per_seq[i1_gap_idx]) + { + ps_dpb_mgr->ai4_gaps_start_frm_num[i1_gap_idx] = INVALID_FRAME_NUM; + ps_dpb_mgr->ai4_gaps_end_frm_num[i1_gap_idx] = 0; + } + } + } + + return OK; +} + +WORD32 imvcd_dpb_do_mmco_for_gaps(mvc_dpb_manager_t *ps_dpb_mgr, UWORD8 u1_num_ref_frames) +{ + mvc_dpb_info_t *ps_next_dpb; + + WORD32 i; + WORD32 i4_error_code; + UWORD8 u1_num_gaps; + UWORD8 u1_num_st_ref_bufs, u1_num_lt_ref_bufs, u1_del_node; + + WORD32 i4_frame_gaps = 1; + + // Sliding window - implements 8.2.5.3, flush out buffers + u1_num_st_ref_bufs = ps_dpb_mgr->u1_num_st_ref_bufs; + u1_num_lt_ref_bufs = ps_dpb_mgr->u1_num_lt_ref_bufs; + + while(1) + { + u1_num_gaps = ps_dpb_mgr->u1_num_gaps; + + if((u1_num_st_ref_bufs + u1_num_lt_ref_bufs + u1_num_gaps + i4_frame_gaps) > + u1_num_ref_frames) + { + if(0 == (u1_num_st_ref_bufs + u1_num_gaps)) + { + i4_frame_gaps = 0; + + ps_dpb_mgr->u1_num_gaps = (u1_num_ref_frames - u1_num_lt_ref_bufs); + } + else + { + u1_del_node = 1; + ps_next_dpb = ps_dpb_mgr->ps_dpb_st_head; + + if(u1_num_st_ref_bufs > 1) + { + for(i = 1; i < (u1_num_st_ref_bufs - 1); i++) + { + if(ps_next_dpb == NULL) + { + return ERROR_DBP_MANAGER_T; + } + + ps_next_dpb = ps_next_dpb->ps_prev_short; + } + + if(ps_next_dpb->ps_prev_short->ps_prev_short != NULL) + { + return ERROR_DBP_MANAGER_T; + } + + if(u1_num_gaps) + { + i4_error_code = imvcd_dpb_delete_gap_frm_sliding( + ps_dpb_mgr, ps_next_dpb->ps_prev_short->ps_au_buf->i4_pic_num, + &u1_del_node); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + if(u1_del_node) + { + u1_num_st_ref_bufs--; + ps_next_dpb->ps_prev_short->b_used_as_ref = false; + ps_next_dpb->ps_prev_short->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_next_dpb->ps_prev_short->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_next_dpb->ps_prev_short->ps_au_buf->i4_pic_buf_id); + + ps_next_dpb->ps_prev_short->ps_au_buf = NULL; + ps_next_dpb->ps_prev_short = NULL; + } + } + else + { + if(u1_num_st_ref_bufs) + { + if(u1_num_gaps) + { + i4_error_code = imvcd_dpb_delete_gap_frm_sliding( + ps_dpb_mgr, ps_next_dpb->ps_au_buf->i4_pic_num, &u1_del_node); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + if(u1_del_node) + { + u1_num_st_ref_bufs--; + ps_next_dpb->b_used_as_ref = false; + ps_next_dpb->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_next_dpb->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_next_dpb->ps_au_buf->i4_pic_buf_id); + + ps_next_dpb->ps_au_buf = NULL; + ps_next_dpb = NULL; + ps_dpb_mgr->ps_dpb_st_head = NULL; + ps_dpb_mgr->u1_num_st_ref_bufs = u1_num_st_ref_bufs; + } + } + else + { + i4_error_code = imvcd_dpb_delete_gap_frm_sliding( + ps_dpb_mgr, INVALID_FRAME_NUM, &u1_del_node); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + if(u1_del_node) + { + return ERROR_DBP_MANAGER_T; + } + } + } + } + } + else + { + ps_dpb_mgr->u1_num_gaps += i4_frame_gaps; + + break; + } + } + + ps_dpb_mgr->u1_num_st_ref_bufs = u1_num_st_ref_bufs; + + return OK; +} + +void imvcd_dpb_delete_nonref_nondisplay_pics(mvc_dpb_manager_t *ps_dpb_mgr) +{ + WORD32 i; + + display_buf_info_t *ps_display_buf_info = ps_dpb_mgr->as_display_buf_info; + + /* remove all gaps marked as unused for ref */ + for(i = 0; (i < MAX_FRAMES) && ps_dpb_mgr->i1_gaps_deleted; i++) + { + if(GAP_FRAME_NUM == ps_display_buf_info[i].i4_frame_num) + { + ps_dpb_mgr->i1_gaps_deleted--; + ps_dpb_mgr->i1_poc_buf_id_entries--; + ps_display_buf_info[i].i4_poc_buf_id = -1; + ps_display_buf_info[i].i4_poc = 0x7fffffff; + ps_display_buf_info[i].i4_frame_num = 0; + } + } +} + +void imvcd_reset_dpb(mvc_dpb_manager_t *ps_dpb_mgr) +{ + WORD32 i; + + mvc_dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info; + + for(i = 0; i < MVC_MAX_REF_PICS; i++) + { + if(ps_dpb_info[i].b_used_as_ref) + { + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_dpb_info[i].ps_au_buf->i4_pic_buf_id); + + ps_dpb_info[i].b_used_as_ref = false; + ps_dpb_info[i].ps_prev_short = NULL; + ps_dpb_info[i].ps_prev_long = NULL; + ps_dpb_info[i].ps_au_buf = NULL; + ps_dpb_info[i].s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_dpb_info[i].s_bot_field.u1_reference_info = UNUSED_FOR_REF; + ps_dpb_info[i].s_top_field.u1_long_term_frame_idx = MVC_MAX_REF_PICS + 1; + ps_dpb_info[i].s_bot_field.u1_long_term_frame_idx = MVC_MAX_REF_PICS + 1; + } + } + + ps_dpb_mgr->u1_num_st_ref_bufs = ps_dpb_mgr->u1_num_lt_ref_bufs = 0; + ps_dpb_mgr->ps_dpb_st_head = NULL; + ps_dpb_mgr->ps_dpb_lt_head = NULL; + ps_dpb_mgr->u1_mmco_error_in_seq = 0; + + /* release all gaps */ + ps_dpb_mgr->u1_num_gaps = 0; + + for(i = 0; i < MAX_FRAMES; i++) + { + ps_dpb_mgr->ai4_gaps_start_frm_num[i] = INVALID_FRAME_NUM; + ps_dpb_mgr->ai4_gaps_end_frm_num[i] = 0; + ps_dpb_mgr->ai1_gaps_per_seq[i] = 0; + } +} + +void imvcd_dpb_release_display_bufs(mvc_dpb_manager_t *ps_dpb_mgr) +{ + WORD32 i, j; + + display_buf_info_t *ps_display_buf_info = ps_dpb_mgr->as_display_buf_info; + + WORD32 i4_min_poc = 0x7fffffff; + WORD32 i4_min_poc_buf_id = 0; + WORD32 i4_min_index = 0; + + imvcd_dpb_delete_nonref_nondisplay_pics(ps_dpb_mgr); + + for(j = 0; j < ps_dpb_mgr->i1_poc_buf_id_entries; j++) + { + i4_min_poc = 0x7fffffff; + + for(i = 0; i < MAX_FRAMES; i++) + { + if(ps_display_buf_info[i].i4_poc_buf_id != -1) + { + /* Checking for <= is necessary to handle cases where there is one + valid buffer with poc set to 0x7FFFFFFF. */ + if(ps_display_buf_info[i].i4_poc <= i4_min_poc) + { + i4_min_poc = ps_display_buf_info[i].i4_poc; + i4_min_poc_buf_id = ps_display_buf_info[i].i4_poc_buf_id; + i4_min_index = i; + } + } + } + + if(DO_NOT_DISP != i4_min_poc_buf_id) + { + ps_dpb_mgr->i4_cur_display_seq++; + + ih264_disp_mgr_add( + ps_dpb_mgr->ps_disp_buf_mgr, i4_min_poc_buf_id, ps_dpb_mgr->i4_cur_display_seq, + ps_dpb_mgr->ps_mvc_au_buf_mgr->aps_buf_id_to_au_buf_map[i4_min_poc_buf_id]); + + ps_display_buf_info[i4_min_index].i4_poc_buf_id = -1; + ps_display_buf_info[i4_min_index].i4_poc = 0x7fffffff; + ps_display_buf_info[i4_min_index].i4_frame_num = 0; + } + else + { + ps_display_buf_info[i4_min_index].i4_poc_buf_id = -1; + ps_display_buf_info[i4_min_index].i4_poc = 0x7fffffff; + ps_display_buf_info[i4_min_index].i4_frame_num = 0; + } + } + + ps_dpb_mgr->i1_poc_buf_id_entries = 0; +} + +void imvcd_assign_pic_num(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_max_frame_num, + WORD32 i4_cur_frame_num, bool b_are_gaps_in_frame_num_value_allowed) +{ + mvc_dpb_info_t *ps_next_dpb; + + WORD32 i; + WORD32 i4_ref_frame_num; + + /* Start from ST head */ + ps_next_dpb = ps_dpb_mgr->ps_dpb_st_head; + + for(i = 0; i < ps_dpb_mgr->u1_num_st_ref_bufs; i++) + { + WORD32 i4_pic_num; + + i4_ref_frame_num = ps_next_dpb->ps_au_buf->i4_pic_num; + + if(i4_ref_frame_num > i4_cur_frame_num) + { + i4_pic_num = i4_ref_frame_num - i4_max_frame_num; + } + else + { + i4_pic_num = i4_ref_frame_num; + } + + ps_next_dpb->ps_au_buf->i4_pic_num = i4_pic_num; + + ps_next_dpb = ps_next_dpb->ps_prev_short; + } + + if(b_are_gaps_in_frame_num_value_allowed && ps_dpb_mgr->u1_num_gaps) + { + WORD32 i4_start_frm, i4_end_frm; + + /* Assign pic numbers for gaps */ + for(i = 0; i < MAX_FRAMES; i++) + { + i4_start_frm = ps_dpb_mgr->ai4_gaps_start_frm_num[i]; + + if(i4_start_frm != INVALID_FRAME_NUM) + { + if(i4_start_frm > i4_cur_frame_num) + { + /* gap's frame_num is before Current frame_num in + decode order */ + i4_start_frm -= i4_max_frame_num; + } + + ps_dpb_mgr->ai4_gaps_start_frm_num[i] = i4_start_frm; + i4_end_frm = ps_dpb_mgr->ai4_gaps_end_frm_num[i]; + + if(i4_end_frm > i4_cur_frame_num) + { + /* gap's frame_num is before Current frame_num in + decode order */ + i4_end_frm -= i4_max_frame_num; + } + + ps_dpb_mgr->ai4_gaps_end_frm_num[i] = i4_end_frm; + } + } + } +} + +/* If there is common node in both lt_list and st_list, then delete it from */ +/* st_list */ +UWORD8 imvcd_dpb_st_lt_deduplicator(mvc_dpb_manager_t *ps_dpb_mgr) +{ + mvc_dpb_info_t *ps_dpb_lt_head = ps_dpb_mgr->ps_dpb_lt_head; + mvc_dpb_info_t *ps_lt_curr_dpb = ps_dpb_mgr->ps_dpb_lt_head; + mvc_dpb_info_t *ps_dpb_st_head = ps_dpb_mgr->ps_dpb_st_head; + + UWORD8 u1_no_of_nodes_deleted = 0; + UWORD8 u1_num_lt_refs = ps_dpb_mgr->u1_num_lt_ref_bufs; + UWORD8 u1_num_st_refs = ps_dpb_mgr->u1_num_st_ref_bufs; + + while(u1_num_lt_refs && ps_dpb_lt_head) + { + if(ps_dpb_st_head && + ((ps_dpb_lt_head->s_bot_field.u1_reference_info | + ps_dpb_lt_head->s_top_field.u1_reference_info) == (IS_SHORT_TERM | IS_LONG_TERM))) + { + mvc_dpb_info_t *ps_st_next_dpb = ps_dpb_st_head; + mvc_dpb_info_t *ps_st_curr_dpb = ps_dpb_st_head; + + while(u1_num_st_refs && ps_st_curr_dpb) + { + if(ps_st_curr_dpb == ps_lt_curr_dpb) + { + if(u1_num_st_refs == ps_dpb_mgr->u1_num_st_ref_bufs) + { + ps_dpb_mgr->ps_dpb_st_head = ps_dpb_mgr->ps_dpb_st_head->ps_prev_short; + ps_st_curr_dpb = ps_dpb_mgr->ps_dpb_st_head; + } + else + { + ps_st_next_dpb->ps_prev_short = ps_st_curr_dpb->ps_prev_short; + } + + ps_dpb_mgr->u1_num_st_ref_bufs--; + u1_no_of_nodes_deleted++; + + break; + } + + ps_st_next_dpb = ps_st_curr_dpb; + ps_st_curr_dpb = ps_st_curr_dpb->ps_prev_short; + u1_num_st_refs--; + } + } + + ps_lt_curr_dpb = ps_lt_curr_dpb->ps_prev_long; + u1_num_lt_refs--; + } + + return u1_no_of_nodes_deleted; +} + +static int qsort_pic_num_compare(const void *pv_au1, const void *pv_au2) +{ + return ((mvc_au_buffer_t **) pv_au1)[0]->i4_pic_num - + ((mvc_au_buffer_t **) pv_au2)[0]->i4_pic_num; +} + +static int qsort_poc_compare(const void *pv_au1, const void *pv_au2) +{ + return ((mvc_au_buffer_t **) pv_au1)[0]->i4_poc - ((mvc_au_buffer_t **) pv_au2)[0]->i4_poc; +} + +static int qsort_lt_idx_compare(const void *pv_au1, const void *pv_au2) +{ + return ((mvc_au_buffer_t **) pv_au1)[0]->u1_long_term_frm_idx - + ((mvc_au_buffer_t **) pv_au2)[0]->u1_long_term_frm_idx; +} + +WORD32 imvcd_init_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, nalu_mvc_ext_t *ps_cur_nalu_mvc_ext, + mvc_au_buffer_t *ps_cur_au, UWORD16 u2_view_order_id) +{ + mvc_dpb_info_t *ps_ref_au_data; + mvc_ivp_ref_data_t *ps_mvc_ivp_ref_data; + + WORD32 i, j; + + mvc_au_buffer_t *aps_st_au_bufs[MVC_MAX_REF_PICS] = {NULL}; + mvc_au_buffer_t *aps_lt_au_bufs[MVC_MAX_REF_PICS] = {NULL}; + mvc_au_buffer_t *aps_ref_pic_buf_lx[2] = {ps_dpb_mgr->as_init_dpb[0], + ps_dpb_mgr->as_init_dpb[1]}; + sps_mvc_ext_t *ps_sps_mvc_ext = ps_dpb_mgr->s_dpb_ivp_ctxt.ps_sps_mvc_ext; + + UWORD16 u2_view_id = ps_cur_nalu_mvc_ext->u2_view_id; + WORD32 i4_cur_poc = ps_cur_au->i4_poc; + bool b_is_b_pic = !!(ps_cur_au->au4_pack_slc_typ[u2_view_order_id] & B_SLC_BIT); + UWORD8 *pu1_num_short_term_refs = ps_dpb_mgr->au1_num_active_st_refs; + UWORD8 *pu1_num_long_term_refs = ps_dpb_mgr->au1_num_active_lt_refs; + UWORD8 au1_total_num_refs[2] = {0}; + + memset(pu1_num_short_term_refs, 0, 2 * sizeof(pu1_num_short_term_refs[0])); + + memset(pu1_num_long_term_refs, 0, 2 * sizeof(pu1_num_long_term_refs[0])); + + ps_ref_au_data = ps_dpb_mgr->ps_dpb_st_head; + + for(i = 0; i < ps_dpb_mgr->u1_num_st_ref_bufs; i++) + { + aps_st_au_bufs[i] = ps_ref_au_data->ps_au_buf; + ps_ref_au_data = ps_ref_au_data->ps_prev_short; + } + + qsort(aps_st_au_bufs, ps_dpb_mgr->u1_num_st_ref_bufs, sizeof(aps_st_au_bufs[0]), + b_is_b_pic ? qsort_poc_compare : qsort_pic_num_compare); + + ps_ref_au_data = ps_dpb_mgr->ps_dpb_lt_head; + + for(i = 0; i < ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + aps_lt_au_bufs[i] = ps_ref_au_data->ps_au_buf; + ps_ref_au_data = ps_ref_au_data->ps_prev_long; + } + + qsort(aps_lt_au_bufs, ps_dpb_mgr->u1_num_lt_ref_bufs, sizeof(aps_lt_au_bufs[0]), + qsort_lt_idx_compare); + + if(b_is_b_pic) + { + for(i = 0; i < ps_dpb_mgr->u1_num_st_ref_bufs; i++) + { + if(aps_st_au_bufs[i]->i4_poc >= i4_cur_poc) + { + break; + } + } + + for(j = i - 1; j >= 0; j--) + { + aps_ref_pic_buf_lx[0][0] = aps_st_au_bufs[j][0]; + aps_ref_pic_buf_lx[0]++; + pu1_num_short_term_refs[0]++; + } + + for(j = i; j < ps_dpb_mgr->u1_num_st_ref_bufs; j++) + { + aps_ref_pic_buf_lx[1][0] = aps_st_au_bufs[j][0]; + aps_ref_pic_buf_lx[1]++; + pu1_num_short_term_refs[1]++; + } + } + else + { + for(i = ps_dpb_mgr->u1_num_st_ref_bufs - 1; i >= 0; i--) + { + aps_ref_pic_buf_lx[0][0] = aps_st_au_bufs[i][0]; + aps_ref_pic_buf_lx[0]++; + pu1_num_short_term_refs[0]++; + } + } + + for(i = 0; i < ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + for(j = 0; j < 1 + ((WORD32) b_is_b_pic); j++) + { + aps_ref_pic_buf_lx[j][0] = aps_lt_au_bufs[i][0]; + aps_ref_pic_buf_lx[j]->u1_long_term_pic_num = + aps_ref_pic_buf_lx[j]->u1_long_term_frm_idx; + aps_ref_pic_buf_lx[j]++; + pu1_num_long_term_refs[j]++; + } + } + + if(0 != u2_view_order_id) + { + ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs = 0; + + for(i = 0; i < 1 + ((WORD32) b_is_b_pic); i++) + { + WORD32 i4_num_refs; + + if(ps_cur_nalu_mvc_ext->u1_anchor_pic_flag) + { + ps_mvc_ivp_ref_data = &ps_sps_mvc_ext->as_anchor_ref_data[i][u2_view_order_id]; + } + else + { + ps_mvc_ivp_ref_data = &ps_sps_mvc_ext->as_non_anchor_ref_data[i][u2_view_order_id]; + } + + i4_num_refs = ps_mvc_ivp_ref_data->u1_num_refs; + + for(j = 0; j < i4_num_refs; j++) + { + mvc_au_buffer_t *ps_au_buf; + mvc_au_mv_pred_t *ps_au_mv_data; + nalu_mvc_ext_t *ps_ref_nalu_mvc_ext; + + WORD32 i4_pic_buf_id; + WORD32 i4_mv_buf_id; + + UWORD16 u2_ref_view_id = ps_mvc_ivp_ref_data->au2_ref_view_ids[j]; + + ps_ref_nalu_mvc_ext = imvcd_get_nalu_mvc_ext( + ps_dpb_mgr->s_dpb_ivp_ctxt.ps_nalu_mvc_exts, u2_view_order_id, u2_ref_view_id); + + if(!ps_ref_nalu_mvc_ext->u1_inter_view_flag) + { + continue; + } + + ps_au_buf = ih264_buf_mgr_get_next_free( + ps_dpb_mgr->ps_mvc_au_buf_mgr->ps_buf_mgr_ctxt, &i4_pic_buf_id); + + if(NULL == ps_au_buf) + { + return ERROR_UNAVAIL_PICBUF_T; + } + else + { + ih264_buf_mgr_set_status(ps_dpb_mgr->ps_mvc_au_buf_mgr->ps_buf_mgr_ctxt, + i4_pic_buf_id, BUF_MGR_REF); + } + + ps_au_mv_data = ih264_buf_mgr_get_next_free( + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr->ps_buf_mgr_ctxt, &i4_mv_buf_id); + + if(NULL == ps_au_mv_data) + { + return ERROR_UNAVAIL_PICBUF_T; + } + else + { + ih264_buf_mgr_set_status(ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr->ps_buf_mgr_ctxt, + i4_mv_buf_id, BUF_MGR_REF); + } + + ps_au_buf->i4_pic_buf_id = i4_pic_buf_id; + ps_au_buf->i4_mv_buf_id = i4_mv_buf_id; + ps_au_buf->s_ivp_data.b_is_ivp_ref = true; + ps_au_buf->s_ivp_data.u2_ref_view_id = u2_ref_view_id; + + imvcd_ivp_buf_copier(ps_cur_au, ps_au_buf, ps_cur_au->ps_au_mv_data, ps_au_mv_data, + u2_ref_view_id, u2_view_id); + + ps_dpb_mgr->ps_mvc_au_buf_mgr->au1_au_buf_id_to_mv_buf_id_map[i4_pic_buf_id] = + i4_mv_buf_id; + ps_dpb_mgr->ps_mvc_au_buf_mgr->aps_buf_id_to_au_buf_map[i4_pic_buf_id] = ps_au_buf; + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr->aps_buf_id_to_mv_pred_buf_map[i4_mv_buf_id] = + ps_au_mv_data; + + ps_dpb_mgr->s_dpb_ivp_ctxt + .au1_au_buf_ids[ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs] = i4_pic_buf_id; + ps_dpb_mgr->s_dpb_ivp_ctxt + .au1_mv_buf_ids[ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs] = i4_mv_buf_id; + + aps_ref_pic_buf_lx[i][0] = ps_au_buf[0]; + + aps_ref_pic_buf_lx[i]++; + pu1_num_short_term_refs[i]++; + ps_dpb_mgr->s_dpb_ivp_ctxt.u4_num_ivp_refs++; + } + } + } + + for(i = 0; i < 1 + ((WORD32) b_is_b_pic); i++) + { + au1_total_num_refs[i] = pu1_num_short_term_refs[i] + pu1_num_long_term_refs[i]; + + if(pu1_num_short_term_refs[i] > MVC_MAX_REF_PICS) + { + return ERROR_NUM_REF; + } + + if(au1_total_num_refs[i] > MVC_MAX_REF_PICS) + { + return ERROR_NUM_REF; + } + + if(0 == au1_total_num_refs[i]) + { + return ERROR_NUM_REF; + } + } + + /* If list0 and list1 entries are same then swap the 0th and 1st entry */ + /* of list 1 */ + { + mvc_au_buffer_t *aps_ref_pic_bufs_lx[2] = {ps_dpb_mgr->as_init_dpb[0], + ps_dpb_mgr->as_init_dpb[1]}; + + if((au1_total_num_refs[0] == au1_total_num_refs[1]) && (au1_total_num_refs[0] > 1)) + { + bool b_swap; + + b_swap = true; + + for(i = 0; i < au1_total_num_refs[0]; i++) + { + if(aps_ref_pic_bufs_lx[0][i] + .as_view_buffers[u2_view_id] + .as_component_bufs[Y] + .pv_data != aps_ref_pic_bufs_lx[1][i] + .as_view_buffers[u2_view_id] + .as_component_bufs[Y] + .pv_data) + { + b_swap = false; + + break; + } + } + + if(b_swap) + { + SWAP(aps_ref_pic_bufs_lx[1][0], aps_ref_pic_bufs_lx[1][1], mvc_au_buffer_t); + } + } + } + + return OK; +} + +void imvcd_dpb_set_missing_refs_to_default(mvc_dpb_manager_t *ps_dpb_mgr, + ref_pic_list_mod_data_t *ps_ref_pic_list_mod_data, + mvc_au_buffer_t *ps_cur_au, UWORD8 u1_pred_lx) +{ + UWORD8 u1_num_refs = ps_dpb_mgr->au1_num_active_st_refs[u1_pred_lx] + + ps_dpb_mgr->au1_num_active_lt_refs[u1_pred_lx]; + + while(u1_num_refs < ps_ref_pic_list_mod_data->au1_num_active_refs[u1_pred_lx]) + { + ps_dpb_mgr->as_init_dpb[u1_pred_lx][u1_num_refs] = ps_cur_au[0]; + ps_dpb_mgr->au1_num_active_st_refs[u1_pred_lx]++; + u1_num_refs++; + } +} + +void imvcd_dpb_normalise_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, UWORD16 u2_buf_mod_bitfield, + UWORD8 u1_num_bufs_modified, UWORD8 u1_pred_lx) +{ + WORD32 i; + + UWORD8 u1_num_ref_bufs = ps_dpb_mgr->au1_num_active_st_refs[u1_pred_lx] + + ps_dpb_mgr->au1_num_active_lt_refs[u1_pred_lx]; + + for(i = 0; i < u1_num_ref_bufs; i++) + { + if(!(u2_buf_mod_bitfield & (1 << i))) + { + ps_dpb_mgr->aps_mod_dpb[u1_pred_lx][u1_num_bufs_modified++] = + &ps_dpb_mgr->as_init_dpb[u1_pred_lx][i]; + } + } +} + +WORD32 imvcd_dpb_reorder_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext, + mvc_au_buffer_t *ps_cur_au, + ref_pic_list_mod_data_t *ps_ref_pic_list_mod_data, + UWORD16 u2_view_order_id) +{ + WORD32 i, j; + + sps_mvc_ext_t *ps_sps_mvc_ext = ps_dpb_mgr->s_dpb_ivp_ctxt.ps_sps_mvc_ext; + + UWORD8 u1_anchor_pic_flag = ps_cur_nalu_mvc_ext->u1_anchor_pic_flag; + WORD32 i4_cur_pic_num = ps_cur_au->i4_pic_num; + WORD32 i4_max_pic_num = ps_dpb_mgr->i4_max_pic_num; + bool b_is_b_pic = !!(ps_cur_au->au4_pack_slc_typ[u2_view_order_id] & B_SLC_BIT); + + for(i = 0; i < 1 + ((WORD32) b_is_b_pic); i++) + { + mvc_ivp_ref_data_t *ps_mvc_ivp_ref_data; + + UWORD16 u2_max_view_idx; + + WORD32 i4_pred_pic_num = i4_cur_pic_num; + WORD16 i2_pred_view_order_id = 0; // -1; Need to check spec and JMVM implementation match + UWORD8 *pu1_modification_of_pic_nums_idc = + ps_ref_pic_list_mod_data->au1_modification_of_pic_nums_idc[i]; + WORD32 *pi4_abs_diff_pic_num_minus1 = + ps_ref_pic_list_mod_data->ai4_abs_diff_pic_num_minus1[i]; + WORD32 *pi4_long_term_pic_num = ps_ref_pic_list_mod_data->ai4_long_term_pic_num[i]; + WORD32 *pi4_abs_diff_view_idx_minus1 = + ps_ref_pic_list_mod_data->ai4_abs_diff_view_idx_minus1[i]; + UWORD8 u1_num_ref_bufs = + ps_dpb_mgr->au1_num_active_st_refs[i] + ps_dpb_mgr->au1_num_active_lt_refs[i]; + UWORD16 u2_buf_mod_bitfield = 0; + UWORD8 u1_num_bufs_modified = 0; + + if(!ps_ref_pic_list_mod_data->au1_ref_pic_list_modification_flag_lx[i] || + (3 == pu1_modification_of_pic_nums_idc[0])) + { + imvcd_dpb_set_missing_refs_to_default(ps_dpb_mgr, ps_ref_pic_list_mod_data, ps_cur_au, + i); + + imvcd_dpb_normalise_ref_pic_list(ps_dpb_mgr, u2_buf_mod_bitfield, u1_num_bufs_modified, + i); + + continue; + } + + ps_mvc_ivp_ref_data = + (0 == u2_view_order_id) + ? NULL + : (u1_anchor_pic_flag + ? &ps_sps_mvc_ext->as_anchor_ref_data[i][u2_view_order_id] + : &ps_sps_mvc_ext->as_non_anchor_ref_data[i][u2_view_order_id]); + u2_max_view_idx = (0 == u2_view_order_id) ? 0 : ps_mvc_ivp_ref_data->u1_num_refs; + + do + { + if((0 == pu1_modification_of_pic_nums_idc[0]) || + (1 == pu1_modification_of_pic_nums_idc[0])) + { + WORD32 i4_mod_pic_num = 1 + pi4_abs_diff_pic_num_minus1[0]; + UWORD8 u1_mod_buf_idx = u1_num_ref_bufs; + + if(pi4_abs_diff_pic_num_minus1[0] > i4_max_pic_num) + { + return ERROR_DBP_MANAGER_T; + } + + if(0 == pu1_modification_of_pic_nums_idc[0]) + { + i4_mod_pic_num = i4_pred_pic_num - i4_mod_pic_num; + + if(i4_mod_pic_num < 0) + { + i4_mod_pic_num += i4_max_pic_num; + } + } + else + { + i4_mod_pic_num = i4_pred_pic_num + i4_mod_pic_num; + + if(i4_mod_pic_num >= i4_max_pic_num) + { + i4_mod_pic_num -= i4_max_pic_num; + } + } + + if(i4_mod_pic_num > i4_cur_pic_num) + { + i4_mod_pic_num -= i4_max_pic_num; + } + + for(j = 0; j < u1_num_ref_bufs; j++) + { + if(ps_dpb_mgr->as_init_dpb[i][j].i4_pic_num == i4_mod_pic_num) + { + u1_mod_buf_idx = j; + + break; + } + } + + if(u1_mod_buf_idx == u1_num_ref_bufs) + { + return ERROR_DBP_MANAGER_T; + } + + ps_dpb_mgr->aps_mod_dpb[i][u1_num_bufs_modified++] = + &ps_dpb_mgr->as_init_dpb[i][u1_mod_buf_idx]; + + u2_buf_mod_bitfield |= (1 << u1_mod_buf_idx); + i4_pred_pic_num = i4_mod_pic_num; + } + else if(2 == pu1_modification_of_pic_nums_idc[0]) + { + WORD32 i4_mod_lt_pic_num = pi4_long_term_pic_num[0]; + UWORD8 u1_mod_buf_idx = u1_num_ref_bufs; + + if(pi4_long_term_pic_num[0] > (MAX_REF_BUFS + 1)) + { + return ERROR_DBP_MANAGER_T; + } + + for(j = 0; j < u1_num_ref_bufs; j++) + { + if(!ps_dpb_mgr->as_init_dpb[i][j].b_is_short_term_ref && + (i4_mod_lt_pic_num == ps_dpb_mgr->as_init_dpb[i][j].u1_long_term_pic_num)) + { + u1_mod_buf_idx = j; + + break; + } + } + + if(u1_mod_buf_idx == u1_num_ref_bufs) + { + return ERROR_DBP_MANAGER_T; + } + + ps_dpb_mgr->aps_mod_dpb[i][u1_num_bufs_modified++] = + &ps_dpb_mgr->as_init_dpb[i][u1_mod_buf_idx]; + + u2_buf_mod_bitfield |= (1 << u1_mod_buf_idx); + } + else if((4 == pu1_modification_of_pic_nums_idc[0]) || + (5 == pu1_modification_of_pic_nums_idc[0])) + { + WORD32 i4_target_view_id; + + WORD32 i4_mod_view_order_id = pi4_abs_diff_view_idx_minus1[0] + 1; + UWORD8 u1_mod_buf_idx = u1_num_ref_bufs; + + if(4 == pu1_modification_of_pic_nums_idc[0]) + { + i4_mod_view_order_id = i2_pred_view_order_id - i4_mod_view_order_id; + + if(i4_mod_view_order_id < 0) + { + i4_mod_view_order_id += u2_max_view_idx; + } + } + else + { + i4_mod_view_order_id = i2_pred_view_order_id + i4_mod_view_order_id; + + if(i4_mod_view_order_id >= u2_max_view_idx) + { + i4_mod_view_order_id -= u2_max_view_idx; + } + } + + if((0 == u2_view_order_id) || + !((i4_mod_view_order_id >= 0) && (i4_mod_view_order_id <= u2_max_view_idx)) || + (NULL == ps_mvc_ivp_ref_data)) + { + return ERROR_DBP_MANAGER_T; + } + + i4_target_view_id = ps_mvc_ivp_ref_data->au2_ref_view_ids[i4_mod_view_order_id]; + + for(j = 0; j < u1_num_ref_bufs; j++) + { + if(ps_dpb_mgr->as_init_dpb[i][j].s_ivp_data.b_is_ivp_ref) + { + if((ps_dpb_mgr->as_init_dpb[i][j].i4_pic_num == i4_cur_pic_num) && + (ps_dpb_mgr->as_init_dpb[i][j].s_ivp_data.u2_ref_view_id == + i4_target_view_id)) + { + u1_mod_buf_idx = j; + + break; + } + } + } + + if(u1_mod_buf_idx == u1_num_ref_bufs) + { + return ERROR_DBP_MANAGER_T; + } + + u2_buf_mod_bitfield |= (1 << u1_mod_buf_idx); + ps_dpb_mgr->aps_mod_dpb[i][u1_num_bufs_modified++] = + &ps_dpb_mgr->as_init_dpb[i][u1_mod_buf_idx]; + i2_pred_view_order_id = i4_mod_view_order_id; + } + else if(3 != pu1_modification_of_pic_nums_idc[0]) + { + return ERROR_REFIDX_ORDER_T; + } + else + { + break; + } + + pu1_modification_of_pic_nums_idc++; + pi4_abs_diff_pic_num_minus1++; + pi4_long_term_pic_num++; + pi4_abs_diff_view_idx_minus1++; + } while(true); + + imvcd_dpb_set_missing_refs_to_default(ps_dpb_mgr, ps_ref_pic_list_mod_data, ps_cur_au, i); + + imvcd_dpb_normalise_ref_pic_list(ps_dpb_mgr, u2_buf_mod_bitfield, u1_num_bufs_modified, i); + } + + return OK; +} + +WORD32 imvcd_dpb_insert_st_node(mvc_dpb_manager_t *ps_dpb_mgr, mvc_au_buffer_t *ps_au_buf) +{ + WORD32 i; + + mvc_dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info; + UWORD8 u1_picture_type = ps_au_buf->u1_picturetype; + + for(i = 0; i < MVC_MAX_REF_PICS; i++) + { + if((ps_dpb_info[i].ps_au_buf == ps_au_buf) && ps_dpb_info[i].b_used_as_ref) + { + /* Can occur only for field bottom pictures */ + if(ps_dpb_info[i].ps_au_buf->u1_pic_type == FRM_PIC) + { + return ERROR_DBP_MANAGER_T; + } + else + { + ps_dpb_info[i].s_bot_field.u1_reference_info = IS_SHORT_TERM; + + return OK; + } + } + + if(!ps_dpb_info[i].b_used_as_ref && + (ps_dpb_info[i].s_top_field.u1_reference_info == UNUSED_FOR_REF) && + (ps_dpb_info[i].s_bot_field.u1_reference_info == UNUSED_FOR_REF)) + { + break; + } + } + + if(i == MVC_MAX_REF_PICS) + { + return ERROR_DBP_MANAGER_T; + } + + ps_dpb_info[i].ps_au_buf = ps_au_buf; + ps_dpb_info[i].ps_prev_short = ps_dpb_mgr->ps_dpb_st_head; + ps_dpb_info[i].b_used_as_ref = true; + + ps_dpb_mgr->ps_dpb_st_head = ps_dpb_info + i; + + ps_dpb_mgr->u1_num_st_ref_bufs++; + + ps_au_buf->b_is_short_term_ref = true; + + if((u1_picture_type & 0x03) == FRM_PIC) + { + ps_dpb_info[i].s_top_field.u1_reference_info = IS_SHORT_TERM; + ps_dpb_info[i].s_bot_field.u1_reference_info = IS_SHORT_TERM; + } + else if((u1_picture_type & 0x03) == TOP_FLD) + { + ps_dpb_info[i].s_top_field.u1_reference_info = IS_SHORT_TERM; + } + else if((u1_picture_type & 0x03) == BOT_FLD) + { + ps_dpb_info[i].s_bot_field.u1_reference_info = IS_SHORT_TERM; + } + + return OK; +} + +static WORD32 imvcd_dpb_delete_gap_frm_mmco(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_frame_num, + UWORD8 *pu1_del_node) +{ + WORD8 i, j; + WORD32 *pi4_start, *pi4_end; + WORD32 i4_start_frm_num, i4_end_frm_num, i4_max_pic_num; + + /* find the least frame num from gaps and current DPB node */ + /* Delete the gaps */ + *pu1_del_node = 1; + pi4_start = ps_dpb_mgr->ai4_gaps_start_frm_num; + pi4_end = ps_dpb_mgr->ai4_gaps_end_frm_num; + i4_max_pic_num = ps_dpb_mgr->i4_max_pic_num; + + if(0 == ps_dpb_mgr->u1_num_gaps) + { + return OK; + } + + if(i4_frame_num < 0) + { + i4_frame_num += i4_max_pic_num; + } + + for(i = 0; i < MAX_FRAMES; i++) + { + i4_start_frm_num = pi4_start[i]; + + if(i4_start_frm_num < 0) + { + i4_start_frm_num += i4_max_pic_num; + } + + if(INVALID_FRAME_NUM != i4_start_frm_num) + { + i4_end_frm_num = pi4_end[i]; + + if(i4_end_frm_num < 0) + { + i4_end_frm_num += i4_max_pic_num; + } + + if((i4_frame_num >= i4_start_frm_num) && (i4_frame_num <= i4_end_frm_num)) + { + break; + } + else + { + if(((i4_frame_num + i4_max_pic_num) >= i4_start_frm_num) && + ((i4_frame_num + i4_max_pic_num) <= i4_end_frm_num)) + { + return ERROR_DBP_MANAGER_T; + } + } + } + } + + /* find frame_num index, in the poc_map which needs to be deleted */ + for(j = 0; j < MAX_FRAMES; j++) + { + if(i4_frame_num == ps_dpb_mgr->as_display_buf_info[j].i4_frame_num) + { + break; + } + } + + if(MAX_FRAMES != i) + { + if(j == MAX_FRAMES) + { + return ERROR_DBP_MANAGER_T; + } + + ps_dpb_mgr->as_display_buf_info[j].i4_poc_buf_id = -1; + ps_dpb_mgr->as_display_buf_info[j].i4_poc = 0x7fffffff; + ps_dpb_mgr->as_display_buf_info[j].i4_frame_num = GAP_FRAME_NUM; + + ps_dpb_mgr->i1_gaps_deleted++; + ps_dpb_mgr->ai1_gaps_per_seq[i]--; + ps_dpb_mgr->u1_num_gaps--; + *pu1_del_node = 0; + + if(0 == ps_dpb_mgr->ai1_gaps_per_seq[i]) + { + ps_dpb_mgr->ai4_gaps_start_frm_num[i] = INVALID_FRAME_NUM; + ps_dpb_mgr->ai4_gaps_end_frm_num[i] = 0; + } + } + else + { + return ERROR_DBP_MANAGER_T; + } + + return OK; +} + +static WORD32 imvcd_dpb_insert_lt_node(mvc_dpb_manager_t *ps_dpb_mgr, mvc_dpb_info_t *ps_new_node, + UWORD32 u4_lt_idx) +{ + WORD32 i; + + mvc_dpb_info_t *ps_next_dpb = ps_dpb_mgr->ps_dpb_lt_head; + + ps_new_node->s_top_field.u1_reference_info = IS_LONG_TERM; + ps_new_node->s_bot_field.u1_reference_info = IS_LONG_TERM; + ps_new_node->s_top_field.u1_long_term_frame_idx = u4_lt_idx; + ps_new_node->s_bot_field.u1_long_term_frame_idx = u4_lt_idx; + ps_new_node->ps_au_buf->u1_long_term_frm_idx = u4_lt_idx; + ps_new_node->b_used_as_ref = true; + + if(ps_dpb_mgr->u1_num_lt_ref_bufs > 0) + { + if(u4_lt_idx < ps_next_dpb->ps_au_buf->u1_long_term_frm_idx) + { + ps_new_node->ps_prev_long = ps_next_dpb; + ps_dpb_mgr->ps_dpb_lt_head = ps_new_node; + } + else + { + ps_next_dpb = ps_next_dpb->ps_prev_long; + + for(i = 1; i < ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + if(ps_next_dpb->ps_au_buf->u1_long_term_frm_idx > u4_lt_idx) + { + ps_new_node->ps_prev_long = ps_next_dpb->ps_prev_long; + ps_next_dpb->ps_prev_long = ps_new_node; + + break; + } + + ps_next_dpb = ps_next_dpb->ps_prev_long; + } + } + } + else + { + ps_dpb_mgr->ps_dpb_lt_head = ps_new_node; + ps_new_node->ps_prev_long = NULL; + } + + ps_new_node->ps_au_buf->b_is_short_term_ref = false; + + ps_dpb_mgr->u1_num_lt_ref_bufs++; + + return OK; +} + +static WORD32 imvcd_dpb_delete_lt_node(mvc_dpb_manager_t *ps_dpb_mgr, UWORD32 u4_lt_idx) +{ + mvc_dpb_info_t *ps_next_dpb; + mvc_dpb_info_t *ps_unmark_node; + + WORD32 i; + + if(ps_dpb_mgr->u1_num_lt_ref_bufs > 0) + { + ps_next_dpb = ps_dpb_mgr->ps_dpb_lt_head; + + if(ps_next_dpb->ps_au_buf->u1_long_term_frm_idx == u4_lt_idx) + { + ps_unmark_node = ps_next_dpb; + } + else + { + for(i = 1; i < ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + if(ps_next_dpb->ps_prev_long->ps_au_buf->u1_long_term_frm_idx == u4_lt_idx) + { + break; + } + + ps_next_dpb = ps_next_dpb->ps_prev_long; + } + + if(i < ps_dpb_mgr->u1_num_lt_ref_bufs) + { + ps_unmark_node = ps_next_dpb->ps_prev_long; + } + else + { + return OK; + } + } + + ps_unmark_node->b_used_as_ref = false; + + if(ps_unmark_node == ps_dpb_mgr->ps_dpb_lt_head) + { + ps_dpb_mgr->ps_dpb_lt_head = ps_next_dpb->ps_prev_long; + } + + ps_unmark_node->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_unmark_node->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_unmark_node->ps_au_buf->i4_pic_buf_id); + + ps_next_dpb->ps_prev_long = ps_unmark_node->ps_prev_long; + ps_unmark_node->ps_prev_long = NULL; + ps_dpb_mgr->u1_num_lt_ref_bufs--; + } + + return OK; +} + +WORD32 imvcd_dpb_delete_st_node_or_make_lt(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_pic_num, + UWORD32 u4_lt_idx) +{ + WORD32 i4_error_code; + + mvc_dpb_info_t *ps_next_dpb = ps_dpb_mgr->ps_dpb_st_head; + mvc_dpb_info_t *ps_unmark_node = NULL; + + UWORD8 u1_del_node = 0, u1_del_st = 0; + WORD32 i = 0; + + if(ps_next_dpb->ps_au_buf->i4_pic_num == i4_pic_num) + { + ps_unmark_node = ps_next_dpb; + } + else + { + for(i = 1; i < ps_dpb_mgr->u1_num_st_ref_bufs; i++) + { + if(ps_next_dpb->ps_prev_short->ps_au_buf->i4_pic_num == i4_pic_num) + { + ps_unmark_node = ps_next_dpb->ps_prev_short; + + break; + } + + ps_next_dpb = ps_next_dpb->ps_prev_short; + } + } + + if(i == ps_dpb_mgr->u1_num_st_ref_bufs) + { + if(ps_dpb_mgr->u1_num_gaps) + { + i4_error_code = imvcd_dpb_delete_gap_frm_mmco(ps_dpb_mgr, i4_pic_num, &u1_del_st); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + else + { + return ERROR_DBP_MANAGER_T; + } + + if(u1_del_st) + { + return ERROR_DBP_MANAGER_T; + } + else + { + return 0; + } + } + + ps_unmark_node->b_used_as_ref = false; + ps_unmark_node->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_unmark_node->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + if(ps_unmark_node == ps_dpb_mgr->ps_dpb_st_head) + { + ps_dpb_mgr->ps_dpb_st_head = ps_next_dpb->ps_prev_short; + } + else + { + ps_next_dpb->ps_prev_short = ps_unmark_node->ps_prev_short; + } + + ps_dpb_mgr->u1_num_st_ref_bufs--; + u1_del_node = 1; + + if(u4_lt_idx == (MAX_REF_BUFS + 1)) + { + if(u1_del_node) + { + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_unmark_node->ps_au_buf->i4_pic_buf_id); + + ps_unmark_node->ps_prev_short = NULL; + } + } + else + { + i4_error_code = imvcd_dpb_delete_lt_node(ps_dpb_mgr, u4_lt_idx); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + i4_error_code = imvcd_dpb_insert_lt_node(ps_dpb_mgr, ps_unmark_node, u4_lt_idx); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + return OK; +} + +WORD32 imvcd_dpb_do_mmco(dpb_commands_t *ps_dpb_cmds, mvc_dpb_manager_t *ps_dpb_mgr, + mvc_au_buffer_t *ps_cur_au, UWORD8 u1_max_num_ref_frames, + UWORD8 u1_curr_pic_in_err) +{ + mvc_dpb_info_t *ps_next_dpb; + + WORD32 i, j; + UWORD8 u1_buf_mode, u1_marked_lt; + UWORD8 u1_num_gaps; + WORD32 i4_error_code; + + UWORD8 u1_del_node = 1; + UWORD8 u1_insert_st_pic = 1; + + // 0 - sliding window; 1 - Adaptive + u1_buf_mode = ps_dpb_cmds->u1_buf_mode; + u1_marked_lt = 0; + u1_num_gaps = ps_dpb_mgr->u1_num_gaps; + + if(!u1_buf_mode) + { + // Sliding window - implements 8.2.5.3 + if((ps_dpb_mgr->u1_num_st_ref_bufs + ps_dpb_mgr->u1_num_lt_ref_bufs + u1_num_gaps) == + u1_max_num_ref_frames) + { + UWORD8 u1_new_node_flag = 1; + + if((0 == ps_dpb_mgr->u1_num_st_ref_bufs) && (0 == u1_num_gaps)) + { + return ERROR_DBP_MANAGER_T; + } + + // Chase the links to reach the last but one picNum, if available + ps_next_dpb = ps_dpb_mgr->ps_dpb_st_head; + + if(ps_dpb_mgr->u1_num_st_ref_bufs > 1) + { + if(ps_next_dpb->ps_au_buf->i4_pic_num == ps_cur_au->i4_pic_num) + { + return ERROR_DBP_MANAGER_T; + } + + for(i = 1; i < (ps_dpb_mgr->u1_num_st_ref_bufs - 1); i++) + { + if(ps_next_dpb == NULL) + { + return ERROR_DBP_MANAGER_T; + } + + if(ps_next_dpb->ps_au_buf->i4_pic_num == ps_cur_au->i4_pic_num) + { + return ERROR_DBP_MANAGER_T; + } + + ps_next_dpb = ps_next_dpb->ps_prev_short; + } + + if(ps_next_dpb->ps_prev_short->ps_prev_short != NULL) + { + return ERROR_DBP_MANAGER_T; + } + + if(u1_new_node_flag) + { + if(u1_num_gaps) + { + i4_error_code = imvcd_dpb_delete_gap_frm_sliding( + ps_dpb_mgr, ps_next_dpb->ps_prev_short->ps_au_buf->i4_pic_num, + &u1_del_node); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + if(u1_del_node) + { + ps_dpb_mgr->u1_num_st_ref_bufs--; + ps_next_dpb->ps_prev_short->b_used_as_ref = false; + ps_next_dpb->ps_prev_short->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_next_dpb->ps_prev_short->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_next_dpb->ps_prev_short->ps_au_buf->i4_pic_buf_id); + + ps_next_dpb->ps_prev_short->ps_au_buf = NULL; + ps_next_dpb->ps_prev_short = NULL; + } + } + } + else + { + if(ps_dpb_mgr->u1_num_st_ref_bufs) + { + i4_error_code = imvcd_dpb_delete_gap_frm_sliding( + ps_dpb_mgr, ps_next_dpb->ps_au_buf->i4_pic_num, &u1_del_node); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + if((ps_next_dpb->ps_au_buf->i4_pic_num != ps_cur_au->i4_pic_num) && u1_del_node) + { + ps_dpb_mgr->u1_num_st_ref_bufs--; + ps_next_dpb->b_used_as_ref = false; + ps_next_dpb->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_next_dpb->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_next_dpb->ps_au_buf->i4_pic_buf_id); + + ps_next_dpb->ps_au_buf = NULL; + ps_next_dpb->ps_prev_short = NULL; + ps_dpb_mgr->ps_dpb_st_head = NULL; + ps_next_dpb = NULL; + } + else if(ps_next_dpb->ps_au_buf->i4_pic_num == ps_cur_au->i4_pic_num) + { + if(u1_curr_pic_in_err) + { + u1_insert_st_pic = 0; + } + else if(ps_dpb_mgr->u1_num_st_ref_bufs > 0) + { + ps_dpb_mgr->u1_num_st_ref_bufs--; + ps_next_dpb->b_used_as_ref = false; + ps_next_dpb->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_next_dpb->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_next_dpb->ps_au_buf->i4_pic_buf_id); + + ps_next_dpb->ps_au_buf = NULL; + ps_next_dpb = NULL; + } + } + } + else + { + i4_error_code = imvcd_dpb_delete_gap_frm_sliding(ps_dpb_mgr, INVALID_FRAME_NUM, + &u1_del_node); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + if(u1_del_node) + { + return ERROR_DBP_MANAGER_T; + } + } + } + } + } + else + { + // Adaptive memory control - implements 8.2.5.4 + struct MMCParams *ps_mmc_params; + + UWORD32 u4_mmco; + UWORD32 u4_diff_pic_num; + WORD32 i4_pic_num; + UWORD32 u4_lt_idx; + + for(j = 0; j < ps_dpb_cmds->u1_num_of_commands; j++) + { + ps_mmc_params = &ps_dpb_cmds->as_mmc_params[j]; + u4_mmco = ps_mmc_params->u4_mmco; + + switch(u4_mmco) + { + case MARK_ST_PICNUM_AS_NONREF: + { + WORD64 i8_pic_num; + + u4_diff_pic_num = ps_mmc_params->u4_diff_pic_num; + i8_pic_num = ps_cur_au->i4_pic_num - ((WORD32) (u4_diff_pic_num + 1)); + + if(IS_OUT_OF_RANGE_S32(i8_pic_num)) + { + return ERROR_DBP_MANAGER_T; + } + + i4_pic_num = i8_pic_num; + + if(ps_dpb_mgr->u1_num_st_ref_bufs > 0) + { + i4_error_code = imvcd_dpb_delete_st_node_or_make_lt(ps_dpb_mgr, i4_pic_num, + MAX_REF_BUFS + 1); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + else + { + UWORD8 u1_dummy; + + i4_error_code = + imvcd_dpb_delete_gap_frm_mmco(ps_dpb_mgr, i4_pic_num, &u1_dummy); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + break; + } + case MARK_LT_INDEX_AS_NONREF: + { + u4_lt_idx = ps_mmc_params->u4_lt_idx; + + i4_error_code = imvcd_dpb_delete_lt_node(ps_dpb_mgr, u4_lt_idx); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + break; + } + case MARK_ST_PICNUM_AS_LT_INDEX: + { + WORD64 i8_pic_num; + + u4_diff_pic_num = ps_mmc_params->u4_diff_pic_num; + + i8_pic_num = ps_cur_au->i4_pic_num - ((WORD32) (u4_diff_pic_num + 1)); + + if(IS_OUT_OF_RANGE_S32(i8_pic_num)) + { + return ERROR_DBP_MANAGER_T; + } + + i4_pic_num = i8_pic_num; + + u4_lt_idx = ps_mmc_params->u4_lt_idx; + + if((ps_dpb_mgr->u1_max_lt_frame_idx == NO_LONG_TERM_INDICIES) || + (u4_lt_idx > ps_dpb_mgr->u1_max_lt_frame_idx)) + { + return ERROR_DBP_MANAGER_T; + } + + if(ps_dpb_mgr->u1_num_st_ref_bufs > 0) + { + i4_error_code = + imvcd_dpb_delete_st_node_or_make_lt(ps_dpb_mgr, i4_pic_num, u4_lt_idx); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + break; + } + case SET_MAX_LT_INDEX: + { + u4_lt_idx = + ps_mmc_params->u4_max_lt_idx_plus1; // Get Max_long_term_index_plus1 + + if((u4_lt_idx <= ps_dpb_mgr->u1_max_lt_frame_idx) && + (ps_dpb_mgr->u1_num_lt_ref_bufs > 0)) + { + mvc_dpb_info_t *ps_nxtDPB; + + // Set all LT buffers with index >= u4_lt_idx to nonreference + ps_nxtDPB = ps_dpb_mgr->ps_dpb_lt_head; + ps_next_dpb = ps_nxtDPB->ps_prev_long; + + if(ps_nxtDPB->ps_au_buf->u1_long_term_frm_idx >= u4_lt_idx) + { + i = 0; + ps_dpb_mgr->ps_dpb_lt_head = NULL; + } + else + { + for(i = 1; i < ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + if(ps_next_dpb->ps_au_buf->u1_long_term_frm_idx >= u4_lt_idx) + { + break; + } + + ps_nxtDPB = ps_next_dpb; + ps_next_dpb = ps_next_dpb->ps_prev_long; + } + + ps_nxtDPB->ps_prev_long = NULL; // Terminate the link of the + // closest LTIndex that is <=Max + } + + ps_dpb_mgr->u1_num_lt_ref_bufs = i; + + if(i == 0) + { + ps_next_dpb = ps_nxtDPB; + } + + for(; i < ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + ps_nxtDPB = ps_next_dpb; + ps_nxtDPB->b_used_as_ref = false; + ps_nxtDPB->s_top_field.u1_reference_info = UNUSED_FOR_REF; + ps_nxtDPB->s_bot_field.u1_reference_info = UNUSED_FOR_REF; + + imvcd_free_ref_bufs(ps_dpb_mgr->ps_mvc_au_buf_mgr, + ps_dpb_mgr->ps_mvc_au_mv_pred_buf_mgr, + ps_nxtDPB->ps_au_buf->i4_pic_buf_id); + + ps_nxtDPB->ps_au_buf = NULL; + + ps_next_dpb = ps_nxtDPB->ps_prev_long; + ps_nxtDPB->ps_prev_long = NULL; + } + } + + if(u4_lt_idx == 0) + { + ps_dpb_mgr->u1_max_lt_frame_idx = NO_LONG_TERM_INDICIES; + } + else + { + ps_dpb_mgr->u1_max_lt_frame_idx = u4_lt_idx - 1; + } + + break; + } + case SET_LT_INDEX: + { + u4_lt_idx = ps_mmc_params->u4_lt_idx; // Get long term index + + if((ps_dpb_mgr->u1_max_lt_frame_idx == NO_LONG_TERM_INDICIES) || + (u4_lt_idx > ps_dpb_mgr->u1_max_lt_frame_idx)) + { + return ERROR_DBP_MANAGER_T; + } + + i4_error_code = imvcd_dpb_insert_st_node(ps_dpb_mgr, ps_cur_au); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + if(ps_dpb_mgr->u1_num_st_ref_bufs > 0) + { + i4_error_code = imvcd_dpb_delete_st_node_or_make_lt( + ps_dpb_mgr, ps_cur_au->i4_pic_num, u4_lt_idx); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + else + { + return ERROR_DBP_MANAGER_T; + } + + u1_marked_lt = 1; + + break; + } + default: + { + break; + } + } + + if((u4_mmco == RESET_REF_PICTURES) || (u4_mmco == RESET_ALL_PICTURES)) + { + i4_pic_num = ps_cur_au->i4_frame_num; + + imvcd_reset_dpb(ps_dpb_mgr); + + ps_cur_au->i4_frame_num = 0; + + if(!u1_marked_lt && u1_insert_st_pic) + { + i4_error_code = imvcd_dpb_insert_st_node(ps_dpb_mgr, ps_cur_au); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + ps_cur_au->i4_frame_num = i4_pic_num; + + return OK; + } + } + } + + if(!u1_marked_lt && u1_insert_st_pic) + { + i4_error_code = imvcd_dpb_insert_st_node(ps_dpb_mgr, ps_cur_au); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + return OK; +} + +WORD32 imvcd_dpb_update_default_index_list(mvc_dpb_manager_t *ps_dpb_mgr) +{ + WORD32 i; + + mvc_dpb_info_t *ps_next_dpb = ps_dpb_mgr->ps_dpb_st_head; + + for(i = 0; i < ps_dpb_mgr->u1_num_st_ref_bufs; i++) + { + ps_dpb_mgr->aps_def_dpb[i] = ps_next_dpb->ps_au_buf; + ps_next_dpb = ps_next_dpb->ps_prev_short; + } + + ps_next_dpb = ps_dpb_mgr->ps_dpb_lt_head; + + for(; i < ps_dpb_mgr->u1_num_st_ref_bufs + ps_dpb_mgr->u1_num_lt_ref_bufs; i++) + { + ps_dpb_mgr->aps_def_dpb[i] = ps_next_dpb->ps_au_buf; + ps_next_dpb = ps_next_dpb->ps_prev_long; + } + + return OK; +} diff --git a/decoder/mvc/imvcd_dpb_manager.h b/decoder/mvc/imvcd_dpb_manager.h new file mode 100644 index 0000000..e0cd46b --- /dev/null +++ b/decoder/mvc/imvcd_dpb_manager.h @@ -0,0 +1,214 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_nalu_parser.h */ +/* */ +/* Description : Functions for MVC NALU parsing */ +/* */ +/*****************************************************************************/ + +#ifndef _IMVCD_DPB_MANAGER_H_ +#define _IMVCD_DPB_MANAGER_H_ +#include + +#include "ih264_typedefs.h" +#include "ih264_error.h" +#include "ih264_buf_mgr.h" +#include "ih264_disp_mgr.h" +#include "imvcd_defs.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +typedef struct mvc_dpb_info_t +{ + mvc_au_buffer_t *ps_au_buf; + + struct mvc_dpb_info_t *ps_prev_short; + + struct mvc_dpb_info_t *ps_prev_long; + + struct field_t s_top_field; + + struct field_t s_bot_field; + + bool b_used_as_ref; + +} mvc_dpb_info_t; + +typedef struct display_buf_info_t +{ + WORD32 i4_poc; + + WORD32 i4_poc_buf_id; + + WORD32 i4_frame_num; +} display_buf_info_t; + +typedef struct dpb_ivp_ctxt_t +{ + sps_mvc_ext_t *ps_sps_mvc_ext; + + nalu_mvc_ext_t *ps_nalu_mvc_exts; + + UWORD8 au1_au_buf_ids[MVC_MAX_REF_PICS]; + + UWORD8 au1_mv_buf_ids[MVC_MAX_REF_PICS]; + + UWORD32 u4_num_ivp_refs; +} dpb_ivp_ctxt_t; + +typedef struct mvc_dpb_manager_t +{ + /** DPB in default index order */ + mvc_au_buffer_t *aps_def_dpb[MVC_MAX_REF_PICS]; + + /** DPB in reordered index order, 0-fwd,1-bwd */ + mvc_au_buffer_t *aps_mod_dpb[2][MVC_MAX_REF_PICS]; + + /** DPB in reordered index order, 0-fwd,1-bwd */ + mvc_au_buffer_t as_init_dpb[2][MVC_MAX_REF_PICS]; + + /** Replicates view level data in 'aps_mod_dpb' */ + pic_buffer_t *aps_view_mod_dpb[2][MVC_MAX_REF_PICS]; + + /** Replicates view level data in 'aps_init_dpb' */ + pic_buffer_t as_view_init_dpb[2][MVC_MAX_REF_PICS]; + + mvc_dpb_info_t as_dpb_info[MVC_MAX_REF_PICS]; + + display_buf_info_t as_display_buf_info[MAX_FRAMES]; + + dpb_ivp_ctxt_t s_dpb_ivp_ctxt; + + mvc_dpb_info_t *ps_dpb_st_head; + + mvc_dpb_info_t *ps_dpb_lt_head; + + mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr; + + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr; + + disp_mgr_t *ps_disp_buf_mgr; + + WORD32 ai4_gaps_start_frm_num[MAX_FRAMES]; + + WORD32 ai4_gaps_end_frm_num[MAX_FRAMES]; + + WORD8 ai1_gaps_per_seq[MAX_FRAMES]; + + UWORD8 au1_num_active_st_refs[2]; + + UWORD8 au1_num_active_lt_refs[2]; + + WORD32 i4_max_pic_num; + + WORD32 i4_display_delay; + + WORD32 i4_cur_display_seq; + + UWORD16 u2_num_views; + + UWORD8 u1_num_st_ref_bufs; + + UWORD8 u1_num_lt_ref_bufs; + + UWORD8 u1_max_lt_frame_idx; + + UWORD8 u1_num_gaps; + + WORD8 i1_poc_buf_id_entries; + + WORD8 i1_gaps_deleted; + + UWORD8 u1_mmco_error_in_seq; + +} mvc_dpb_manager_t; + +/* Function declarations */ +extern void imvcd_init_dpb_mgr(mvc_dpb_manager_t *ps_dpb_mgr, mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr, + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr, + disp_mgr_t *ps_disp_buf_mgr); + +extern WORD32 imvcd_dpb_assign_display_seq(mvc_dpb_manager_t *ps_dpb_mgr); + +extern WORD32 imvcd_dpb_insert_pic_in_display_list(mvc_dpb_manager_t *ps_dpb_mgr, + WORD32 i4_display_poc, UWORD32 u4_frame_num, + WORD32 i4_buf_id); + +extern WORD32 imvcd_dpb_do_mmco_for_gaps(mvc_dpb_manager_t *ps_dpb_mgr, UWORD8 u1_num_ref_frames); + +extern void imvcd_dpb_delete_nonref_nondisplay_pics(mvc_dpb_manager_t *ps_dpb_mgr); + +extern void imvcd_reset_dpb(mvc_dpb_manager_t *ps_dpb_mgr); + +extern void imvcd_dpb_release_display_bufs(mvc_dpb_manager_t *ps_dpb_mgr); + +extern void imvcd_assign_pic_num(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_max_frame_num, + WORD32 i4_cur_frame_num, + bool b_are_gaps_in_frame_num_value_allowed); + +extern UWORD8 imvcd_dpb_st_lt_deduplicator(mvc_dpb_manager_t *ps_dpb_mgr); + +extern WORD32 imvcd_init_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext, + mvc_au_buffer_t *ps_cur_au, UWORD16 u2_view_order_id); + +extern WORD32 imvcd_dpb_reorder_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext, + mvc_au_buffer_t *ps_cur_au, + ref_pic_list_mod_data_t *ps_ref_pic_list_mod_data, + UWORD16 u2_view_order_id); + +extern WORD32 imvcd_dpb_insert_st_node(mvc_dpb_manager_t *ps_dpb_mgr, mvc_au_buffer_t *ps_au_buf); + +extern WORD32 imvcd_dpb_delete_st_node_or_make_lt(mvc_dpb_manager_t *ps_dpb_mgr, + WORD32 i4_frame_num, UWORD32 u4_lt_idx); + +extern WORD32 imvcd_dpb_do_mmco(dpb_commands_t *ps_dpb_cmds, mvc_dpb_manager_t *ps_dpb_mgr, + mvc_au_buffer_t *ps_cur_au, UWORD8 u1_max_num_ref_frames, + UWORD8 u1_curr_pic_in_err); + +extern WORD32 imvcd_dpb_update_default_index_list(mvc_dpb_manager_t *ps_dpb_mgr); + +extern void imvcd_dpb_set_display_num(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_display_num); + +extern void imvcd_dpb_set_max_pic_num(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_max_pic_num); + +extern void imvcd_dpb_set_num_views(mvc_dpb_manager_t *ps_dpb_mgr, UWORD16 u2_num_views); + +extern void imvcd_dpb_set_display_delay(mvc_dpb_manager_t *ps_dpb_mgr, WORD32 i4_display_delay); + +extern void imvcd_dpb_init_au_bufs(mvc_dpb_manager_t *ps_dpb_mgr, mvc_au_buffer_t *ps_cur_au); + +extern void imvcd_dpb_init_view_bufs(mvc_dpb_manager_t *ps_dpb_mgr, UWORD16 u2_view_order_id, + UWORD16 u2_view_id); + +extern void imvcd_dpb_init_ivp_ctxt(mvc_dpb_manager_t *ps_dpb_mgr, sps_mvc_ext_t *ps_sps_mvc_ext, + nalu_mvc_ext_t *ps_nalu_mvc_exts); + +extern void imvcd_dpb_reset_ivp_ctxt(mvc_dpb_manager_t *ps_dpb_mgr); + +extern pic_buffer_t **imvcd_dpb_get_view_ref_pic_list(mvc_dpb_manager_t *ps_dpb_mgr, + UWORD16 u2_view_order_id, UWORD16 u2_view_id, + UWORD8 u1_pred_dir); + +#endif diff --git a/decoder/mvc/imvcd_error_handler.c b/decoder/mvc/imvcd_error_handler.c new file mode 100644 index 0000000..0ba41e8 --- /dev/null +++ b/decoder/mvc/imvcd_error_handler.c @@ -0,0 +1,394 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_error_handler.c */ +/* */ +/* Description : Functions for error handling */ +/* */ +/*****************************************************************************/ + +#include "ih264_typedefs.h" +#include "iv.h" +#include "imvcd.h" +#include "ih264_macros.h" +#include "imvc_defs.h" +#include "ih264d_defs.h" +#include "ih264d_error_handler.h" +#include "ih264d_nal.h" +#include "ih264d_structs.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +static IV_API_CALL_STATUS_T imvcd_check_invalid_numViews(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + UWORD8 u1_num_valid_subset_sps_found = 0; + UWORD16 u2_max_views = 1; + + if((ps_mvcd_ctxt->u1_num_subset_sps == 0) && (ps_mvcd_ctxt->u2_num_views_decoded > 0)) + { + return IV_FAIL; + } + + for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++) + { + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid) + { + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_mvc_ext.u2_num_views > MAX_NUM_VIEWS) + { + return IV_FAIL; + } + + u2_max_views = + MAX(u2_max_views, ps_mvcd_ctxt->as_subset_sps[i].s_sps_mvc_ext.u2_num_views); + u1_num_valid_subset_sps_found++; + } + } + + if(u1_num_valid_subset_sps_found > ps_mvcd_ctxt->u1_num_subset_sps) + { + return IV_FAIL; + } + + if(ps_mvcd_ctxt->u2_num_views > u2_max_views) + { + return IV_FAIL; + } + + if(ps_mvcd_ctxt->u2_num_views_decoded >= u2_max_views) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_check_sps_and_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + UWORD32 i; + UWORD32 u4_cnt; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UWORD32 u4_num_sps = ps_mvcd_ctxt->u1_num_sps; + UWORD32 u4_num_subset_sps = ps_mvcd_ctxt->u1_num_subset_sps; + WORD32 i4_max_mb_addr = INT32_MIN; + + i = 0; + u4_cnt = 0; + + while((u4_cnt < u4_num_sps) && (i < MAX_NUM_SEQ_PARAMS)) + { + if(ps_view_ctxt->ps_sps[i].u1_is_valid) + { + u4_cnt++; + + if(i4_max_mb_addr == INT32_MIN) + { + i4_max_mb_addr = ps_view_ctxt->ps_sps[i].u2_max_mb_addr; + } + else if(i4_max_mb_addr != ps_view_ctxt->ps_sps[i].u2_max_mb_addr) + { + return IV_FAIL; + } + + if(ps_view_ctxt->ps_sps[i].u2_max_mb_addr > + imvcd_get_num_mbs_in_level(ps_view_ctxt->ps_sps[i].u1_level_idc)) + { + return IV_FAIL; + } + + if(ps_view_ctxt->ps_sps[i].u1_mb_aff_flag) + { + return IV_FAIL; + } + + if(!ps_view_ctxt->ps_sps[i].u1_frame_mbs_only_flag) + { + return IV_FAIL; + } + } + + i++; + } + + if(u4_cnt != u4_num_sps) + { + return IV_FAIL; + } + + i = 0; + u4_cnt = 0; + + while((u4_cnt < u4_num_subset_sps) && (i < MAX_NUM_SEQ_PARAMS)) + { + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid) + { + u4_cnt++; + + if(i4_max_mb_addr == INT32_MIN) + { + i4_max_mb_addr = ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u2_max_mb_addr; + } + else if(i4_max_mb_addr != ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u2_max_mb_addr) + { + return IV_FAIL; + } + + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u2_max_mb_addr > + imvcd_get_num_mbs_in_level(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_level_idc)) + { + return IV_FAIL; + } + + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_mb_aff_flag) + { + return IV_FAIL; + } + + if(!ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_frame_mbs_only_flag) + { + return IV_FAIL; + } + } + + i++; + } + + if(u4_cnt != u4_num_subset_sps) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T imvcd_check_pps(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + bool b_is_valid_pps_found = false; + + for(i = 0; i < MAX_NUM_PIC_PARAMS; i++) + { + if(ps_view_ctxt->ps_pps[i].u1_is_valid) + { + b_is_valid_pps_found = true; + + if(ps_view_ctxt->ps_pps[i].u1_frame_cropping_flag) + { + return IV_FAIL; + } + + if(ps_view_ctxt->ps_pps[i].u1_num_slice_groups != 1) + { + return IV_FAIL; + } + } + } + + return b_is_valid_pps_found ? IV_SUCCESS : IV_FAIL; +} + +static IV_API_CALL_STATUS_T imvcd_check_num_view_slices_in_au(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_ip_t *ps_ip) +{ + AVC_EXT_NALU_ID_T e_nalu_id; + + UWORD16 u2_num_view_slices_in_au = 0; + UWORD8 *pu1_input_buffer = (UWORD8 *) ps_ip->s_ivd_ip.pv_stream_buffer; + UWORD32 u4_num_bytes_remaining = ps_ip->s_ivd_ip.u4_num_Bytes; + + while(true) + { + UWORD32 u4_length_of_start_code = 0; + UWORD32 u4_next_is_aud = 0; + WORD32 i4_nalu_length = ih264d_find_start_code(pu1_input_buffer, 0, u4_num_bytes_remaining, + &u4_length_of_start_code, &u4_next_is_aud); + + if(i4_nalu_length <= 0) + { + break; + } + + if((0 != u4_next_is_aud) && (1 != u4_next_is_aud)) + { + break; + } + + if(u4_length_of_start_code < (NUM_OF_ZERO_BYTES_BEFORE_START_CODE + 1)) + { + break; + } + + e_nalu_id = NAL_UNIT_TYPE(pu1_input_buffer[u4_length_of_start_code]); + u2_num_view_slices_in_au += (SLICE_NON_IDR == e_nalu_id) || (SLICE_IDR == e_nalu_id) || + (CODED_SLICE_EXTENSION == e_nalu_id); + + if(((WORD64) u4_num_bytes_remaining) <= + ((WORD64) (((WORD64) u4_length_of_start_code) + ((WORD64) i4_nalu_length)))) + { + break; + } + else + { + pu1_input_buffer += u4_length_of_start_code + i4_nalu_length; + u4_num_bytes_remaining -= u4_length_of_start_code + i4_nalu_length; + } + + if(u2_num_view_slices_in_au == ps_mvcd_ctxt->u2_num_views) + { + break; + } + } + + return (u2_num_view_slices_in_au != ps_mvcd_ctxt->u2_num_views) ? IV_FAIL : IV_SUCCESS; +} + +IV_API_CALL_STATUS_T imvcd_au_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_ip_t *ps_ip) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + if(ps_mvcd_ctxt->b_header_only_decode) + { + return IV_FAIL; + } + + if(!ps_view_ctxt->init_done) + { + return IV_FAIL; + } + + if(IV_FAIL == imvcd_check_invalid_numViews(ps_mvcd_ctxt)) + { + return IV_FAIL; + } + + if(IV_FAIL == imvcd_check_sps_and_subset_sps(ps_mvcd_ctxt)) + { + return IV_FAIL; + } + + if(IV_FAIL == imvcd_check_pps(ps_mvcd_ctxt)) + { + return IV_FAIL; + } + + if(!ps_mvcd_ctxt->b_flush_enabled) + { + if(IV_FAIL == imvcd_check_num_view_slices_in_au(ps_mvcd_ctxt, ps_ip)) + { + return IV_FAIL; + } + } + + return IV_SUCCESS; +} + +IV_API_CALL_STATUS_T imvcd_view_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + nalu_mvc_ext_t *ps_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + bool b_is_idr_slice = imvcd_is_idr_au(ps_mvcd_ctxt); + + if(b_is_idr_slice && (ps_view_ctxt->ps_cur_slice->u1_slice_type != ISLICE)) + { + return IV_FAIL; + } + + if(ps_view_ctxt->u1_first_slice_in_stream && !b_is_idr_slice) + { + return IV_FAIL; + } + + if(ps_nalu_mvc_ext->u2_view_id != 0) + { + subset_sps_t *ps_subset_sps = + ps_mvcd_ctxt + ->aps_pps_id_to_subset_sps_map[ps_view_ctxt->ps_cur_pps->u1_pic_parameter_set_id]; + + if((NULL == ps_subset_sps) || !ps_subset_sps->s_sps_data.u1_is_valid) + { + return IV_FAIL; + } + + if(0 == ps_mvcd_ctxt->u1_num_subset_sps) + { + return IV_FAIL; + } + + if(ps_nalu_mvc_ext->u2_view_id >= ps_subset_sps->s_sps_mvc_ext.u2_num_views) + { + return IV_FAIL; + } + } + else + { + if(ps_mvcd_ctxt->u2_num_views_decoded > 0) + { + return IV_FAIL; + } + } + + if(!ps_view_ctxt->u4_first_slice_in_pic || (ps_view_ctxt->u2_cur_slice_num > 0)) + { + return IV_FAIL; + } + + if(ps_view_ctxt->u4_first_slice_in_pic && + (ps_view_ctxt->ps_cur_slice->u2_first_mb_in_slice != 0)) + { + return IV_FAIL; + } + + if(ps_view_ctxt->ps_cur_slice->u1_mmco_equalto5) + { + return IV_FAIL; + } + + for(i = 0; i < ps_mvcd_ctxt->u2_num_views_decoded; i++) + { + if(ps_mvcd_ctxt->as_slices[i].i4_poc != ps_view_ctxt->ps_cur_slice->i4_poc) + { + return IV_FAIL; + } + + if(ps_mvcd_ctxt->as_slices[i].u2_frame_num != ps_view_ctxt->ps_cur_slice->u2_frame_num) + { + return IV_FAIL; + } + } + + if(SKIP_NONE != ps_view_ctxt->u4_skip_frm_mask) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} diff --git a/decoder/mvc/imvcd_error_handler.h b/decoder/mvc/imvcd_error_handler.h new file mode 100644 index 0000000..5c5d702 --- /dev/null +++ b/decoder/mvc/imvcd_error_handler.h @@ -0,0 +1,39 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ +/*****************************************************************************/ +/* */ +/* File Name : imvcd_error_handler.h */ +/* */ +/* Description : Functions for error handling */ +/* */ +/*****************************************************************************/ + +#ifndef _IMVCD_ERROR_HANDLER_H_ +#define _IMVCD_ERROR_HANDLER_H_ + +#include "iv.h" +#include "imvcd.h" +#include "imvcd_structs.h" + +extern IV_API_CALL_STATUS_T imvcd_au_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt, + imvcd_video_decode_ip_t *ps_ip); + +extern IV_API_CALL_STATUS_T imvcd_view_error_checks(mvc_dec_ctxt_t *ps_mvcd_ctxt); +#endif diff --git a/decoder/mvc/imvcd_nalu_parser.c b/decoder/mvc/imvcd_nalu_parser.c new file mode 100644 index 0000000..02738e2 --- /dev/null +++ b/decoder/mvc/imvcd_nalu_parser.c @@ -0,0 +1,797 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_nalu_parser.h */ +/* */ +/* Description : Functions for MVC NALU parsing */ +/* */ +/*****************************************************************************/ +#include + +#include "ih264_typedefs.h" +#include "iv.h" +#include "imvcd.h" +#include "ih264d_error_handler.h" +#include "ih264d_bitstrm.h" +#include "ih264d_defs.h" +#include "ih264d_nal.h" +#include "ih264d_parse_cavlc.h" +#include "ih264d_structs.h" +#include "ih264d_vui.h" +#include "imvcd_defs.h" +#include "imvcd_slice_functions.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +static WORD32 imvcd_nalu_mvc_ext_parser(mvc_dec_ctxt_t *ps_mvcd_ctxt, dec_bit_stream_t *ps_bitstrm) +{ + nalu_mvc_ext_t *ps_nalu_mvc_ext = + &ps_mvcd_ctxt->as_nalu_mvc_ext[ps_mvcd_ctxt->u2_num_views_decoded]; + + ps_nalu_mvc_ext->u1_non_idr_flag = ih264d_get_bit_h264(ps_bitstrm); + ps_nalu_mvc_ext->u1_priority_id = ih264d_get_bits_h264(ps_bitstrm, 6); + ps_nalu_mvc_ext->u2_view_id = ih264d_get_bits_h264(ps_bitstrm, 10); + ps_nalu_mvc_ext->u1_temporal_id = ih264d_get_bits_h264(ps_bitstrm, 3); + ps_nalu_mvc_ext->u1_anchor_pic_flag = ih264d_get_bit_h264(ps_bitstrm); + ps_nalu_mvc_ext->u1_inter_view_flag = ih264d_get_bit_h264(ps_bitstrm); + + if(0 == ih264d_get_bit_h264(ps_bitstrm)) + { + return IVD_INVALID_BITSTREAM; + } + + if(ps_nalu_mvc_ext->u2_view_id >= MAX_NUM_VIEWS) + { + return IVD_INVALID_BITSTREAM; + } + + return OK; +} + +static WORD32 imvcd_parse_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt, dec_bit_stream_t *ps_bitstrm) +{ + subset_sps_t *ps_subset_sps; + + WORD32 i, j, k; + UWORD8 u1_profile_idc; + UWORD8 au1_constraint_set_flags[6]; + UWORD8 u1_level_idc; + UWORD8 u1_seq_parameter_set_id; + UWORD32 *pu4_bitstrm_buf = ps_bitstrm->pu4_buffer; + UWORD32 *pu4_bitstrm_ofst = &ps_bitstrm->u4_ofst; + UWORD32 u4_temp; + UWORD16 u2_num_views_m1; + UWORD8 u1_num_refs; + UWORD8 u1_num_level_values_signalled_m1; + UWORD8 u2_num_ops_m1; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + WORD32 i4_error_code = OK; + + u1_profile_idc = ih264d_get_bits_h264(ps_bitstrm, 8); + + for(i = 0; i < 6; i++) + { + au1_constraint_set_flags[i] = ih264d_get_bit_h264(ps_bitstrm); + } + + if((u1_profile_idc != MULTIVIEW_HIGH_PROFILE_IDC) || (au1_constraint_set_flags[1] == 1)) + { + return ERROR_FEATURE_UNAVAIL; + } + + /*****************************************************/ + /* Read reserved_zero_2bits (2 bits) */ + /*****************************************************/ + ih264d_get_bits_h264(ps_bitstrm, 2); + + u1_level_idc = ih264d_get_bits_h264(ps_bitstrm, 8); + + u4_temp = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + u1_seq_parameter_set_id = u4_temp; + + if(u4_temp & MASK_ERR_SEQ_SET_ID) + { + return ERROR_INV_SPS_PPS_T; + } + + ps_subset_sps = &ps_mvcd_ctxt->as_subset_sps[u1_seq_parameter_set_id]; + + /* Accounting for the idiocy in 'ih264d_parse_pps' */ + ps_subset_sps->s_sps_data.u1_profile_idc = HIGH_PROFILE_IDC; + ps_subset_sps->s_sps_data.u1_level_idc = u1_level_idc; + ps_subset_sps->s_sps_data.u1_seq_parameter_set_id = u1_seq_parameter_set_id; + + ps_subset_sps->s_sps_data.i4_chroma_format_idc = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.i4_chroma_format_idc != 1) + { + return ERROR_FEATURE_UNAVAIL; + } + + ps_subset_sps->s_sps_data.i4_bit_depth_luma_minus8 = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.i4_bit_depth_luma_minus8 != 0) + { + return ERROR_FEATURE_UNAVAIL; + } + + ps_subset_sps->s_sps_data.i4_bit_depth_chroma_minus8 = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.i4_bit_depth_chroma_minus8 != 0) + { + return ERROR_FEATURE_UNAVAIL; + } + + ps_subset_sps->s_sps_data.i4_qpprime_y_zero_transform_bypass_flag = + ih264d_get_bit_h264(ps_bitstrm); + + if(ps_subset_sps->s_sps_data.i4_qpprime_y_zero_transform_bypass_flag != 0) + { + return ERROR_INV_SPS_PPS_T; + } + + ps_subset_sps->s_sps_data.i4_seq_scaling_matrix_present_flag = ih264d_get_bit_h264(ps_bitstrm); + + if(ps_subset_sps->s_sps_data.i4_seq_scaling_matrix_present_flag) + { + for(i = 0; i < 8; i++) + { + ps_subset_sps->s_sps_data.u1_seq_scaling_list_present_flag[i] = + ih264d_get_bit_h264(ps_bitstrm); + } + } + + ps_subset_sps->s_sps_data.u1_bits_in_frm_num = + 4 + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.u1_bits_in_frm_num > MAX_BITS_IN_FRAME_NUM) + { + return ERROR_INV_SPS_PPS_T; + } + + ps_subset_sps->s_sps_data.u2_u4_max_pic_num_minus1 = + (1 << (ps_subset_sps->s_sps_data.u1_bits_in_frm_num)) - 1; + + ps_subset_sps->s_sps_data.u1_pic_order_cnt_type = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.u1_pic_order_cnt_type > MAX_PIC_ORDER_CNT_TYPE) + { + return ERROR_INV_POC_TYPE_T; + } + + ps_subset_sps->s_sps_data.u1_num_ref_frames_in_pic_order_cnt_cycle = 1; + + if(ps_subset_sps->s_sps_data.u1_pic_order_cnt_type == 0) + { + ps_subset_sps->s_sps_data.u1_log2_max_pic_order_cnt_lsb_minus = + 4 + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.u1_log2_max_pic_order_cnt_lsb_minus > MAX_BITS_IN_POC_LSB) + { + return ERROR_INV_SPS_PPS_T; + } + + ps_subset_sps->s_sps_data.i4_max_pic_order_cntLsb = + (1 << ps_subset_sps->s_sps_data.u1_log2_max_pic_order_cnt_lsb_minus); + } + else if(ps_subset_sps->s_sps_data.u1_pic_order_cnt_type == 1) + { + ps_subset_sps->s_sps_data.u1_delta_pic_order_always_zero_flag = + ih264d_get_bit_h264(ps_bitstrm); + + ps_subset_sps->s_sps_data.i4_ofst_for_non_ref_pic = + ih264d_sev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + ps_subset_sps->s_sps_data.i4_ofst_for_top_to_bottom_field = + ih264d_sev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + ps_subset_sps->s_sps_data.u1_num_ref_frames_in_pic_order_cnt_cycle = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.u1_num_ref_frames_in_pic_order_cnt_cycle > MVC_MAX_REF_PICS) + { + return ERROR_INV_SPS_PPS_T; + } + + for(i = 0; i < ps_subset_sps->s_sps_data.u1_num_ref_frames_in_pic_order_cnt_cycle; i++) + { + ps_subset_sps->s_sps_data.i4_ofst_for_ref_frame[i] = + ih264d_sev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + } + + ps_subset_sps->s_sps_data.u1_num_ref_frames = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if((ps_subset_sps->s_sps_data.u1_num_ref_frames > MVC_MAX_REF_PICS)) + { + return ERROR_NUM_REF; + } + + ps_subset_sps->s_sps_data.u1_gaps_in_frame_num_value_allowed_flag = + ih264d_get_bit_h264(ps_bitstrm); + + ps_subset_sps->s_sps_data.u2_frm_wd_in_mbs = 1 + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.u2_frm_wd_in_mbs > (H264_MAX_FRAME_WIDTH >> 4)) + { + return IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED; + } + + ps_subset_sps->s_sps_data.u2_frm_ht_in_mbs = 1 + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + if(ps_subset_sps->s_sps_data.u2_frm_ht_in_mbs > (H264_MAX_FRAME_HEIGHT >> 4)) + { + return IVD_STREAM_WIDTH_HEIGHT_NOT_SUPPORTED; + } + + ps_subset_sps->s_sps_data.u2_max_mb_addr = + ps_subset_sps->s_sps_data.u2_frm_wd_in_mbs * ps_subset_sps->s_sps_data.u2_frm_ht_in_mbs - 1; + + ps_subset_sps->s_sps_data.u2_total_num_of_mbs = ps_subset_sps->s_sps_data.u2_max_mb_addr + 1; + + ps_subset_sps->s_sps_data.u1_frame_mbs_only_flag = ih264d_get_bit_h264(ps_bitstrm); + + if(!ps_subset_sps->s_sps_data.u1_frame_mbs_only_flag) + { + return ERROR_FEATURE_UNAVAIL; + } + + ps_subset_sps->s_sps_data.u1_mb_aff_flag = 0; + + ps_subset_sps->s_sps_data.u1_direct_8x8_inference_flag = ih264d_get_bit_h264(ps_bitstrm); + + /* Frame cropping flag */ + u4_temp = ih264d_get_bit_h264(ps_bitstrm); + + if(u4_temp) + { + ps_subset_sps->s_disp_offsets.u2_left_offset = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_disp_offsets.u2_right_offset = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_disp_offsets.u2_top_offset = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_disp_offsets.u2_bottom_offset = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + else + { + memset(&ps_subset_sps->s_disp_offsets, 0, sizeof(ps_subset_sps->s_disp_offsets)); + } + + ps_subset_sps->s_sps_data.u1_vui_parameters_present_flag = ih264d_get_bit_h264(ps_bitstrm); + + if(ps_subset_sps->s_sps_data.u1_vui_parameters_present_flag) + { + i4_error_code = ih264d_parse_vui_parametres(&ps_subset_sps->s_sps_data.s_vui, ps_bitstrm); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + if(ih264d_get_bit_h264(ps_bitstrm) != 1) + { + return ERROR_INV_SPS_PPS_T; + } + + u2_num_views_m1 = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.u2_num_views = 1 + u2_num_views_m1; + + if(u2_num_views_m1 > MAX_NUM_VIEWS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + if(ps_view_ctxt->i4_decode_header) + { + ps_mvcd_ctxt->u2_num_views = MAX(ps_mvcd_ctxt->u2_num_views, 1 + u2_num_views_m1); + } + else if(ps_mvcd_ctxt->u2_num_views != (1 + u2_num_views_m1)) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(i = 0; i <= u2_num_views_m1; i++) + { + ps_subset_sps->s_sps_mvc_ext.au2_view_ids[i] = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + + for(i = 0; i < 2; i++) + { + ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[i][0].u1_num_refs = 0; + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[i][0].u1_num_refs = 0; + } + + for(i = 1; i <= u2_num_views_m1; i++) + { + u1_num_refs = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[0][i].u1_num_refs = u1_num_refs; + + if(u1_num_refs > MAX_NUM_IVP_REFS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(j = 0; j < u1_num_refs; j++) + { + ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[0][i].au2_ref_view_ids[j] = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + + u1_num_refs = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[1][i].u1_num_refs = u1_num_refs; + + if(u1_num_refs > MAX_NUM_IVP_REFS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(j = 0; j < u1_num_refs; j++) + { + ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[1][i].au2_ref_view_ids[j] = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + } + + for(i = 1; i <= u2_num_views_m1; i++) + { + u1_num_refs = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[0][i].u1_num_refs = u1_num_refs; + + if(u1_num_refs > MAX_NUM_IVP_REFS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(j = 0; j < u1_num_refs; j++) + { + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[0][i].au2_ref_view_ids[j] = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + + u1_num_refs = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[1][i].u1_num_refs = u1_num_refs; + + if(u1_num_refs > MAX_NUM_IVP_REFS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(j = 0; j < u1_num_refs; j++) + { + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[1][i].au2_ref_view_ids[j] = + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + } + + u1_num_level_values_signalled_m1 = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.u1_num_level_values_signalled = + u1_num_level_values_signalled_m1 + 1; + + if(u1_num_level_values_signalled_m1 >= MAX_NUM_LEVEL_VALUES_SIGNALLED) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(i = 0; i <= u1_num_level_values_signalled_m1; i++) + { + ps_subset_sps->s_sps_mvc_ext.as_mvc_level_info[i].u4_level_idc = + ih264d_get_bits_h264(ps_bitstrm, 8); + + u2_num_ops_m1 = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + ps_subset_sps->s_sps_mvc_ext.as_mvc_level_info->as_mvc_op_data[i].u2_num_ops = + 1 + u2_num_ops_m1; + + if(u2_num_ops_m1 >= MAX_NUM_OPERATING_POINTS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(j = 0; j <= u2_num_ops_m1; j++) + { + UWORD16 u2_num_target_views_m1; + + ps_subset_sps->s_sps_mvc_ext.as_mvc_level_info->as_mvc_op_data[j].u1_temporal_id = + ih264d_get_bits_h264(ps_bitstrm, 3); + + u2_num_target_views_m1 = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + + ps_subset_sps->s_sps_mvc_ext.as_mvc_level_info->as_mvc_op_data[j].u2_num_target_views = + 1 + u2_num_target_views_m1; + + if(u2_num_target_views_m1 >= MAX_NUM_VIEWS) + { + return ERROR_INVALID_SEQ_PARAM; + } + + for(k = 0; k <= u2_num_target_views_m1; k++) + { + ps_subset_sps->s_sps_mvc_ext.as_mvc_level_info->as_mvc_op_data[j] + .au2_target_view_ids[k] = ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + + ps_subset_sps->s_sps_mvc_ext.as_mvc_level_info->as_mvc_op_data[j].u2_num_views = + (UWORD16) 1 + ih264d_uev(pu4_bitstrm_ofst, pu4_bitstrm_buf); + } + } + + ps_subset_sps->u1_mvc_vui_parameters_present_flag = ih264d_get_bit_h264(ps_bitstrm); + + if(ps_subset_sps->u1_mvc_vui_parameters_present_flag) + { + return ERROR_INV_SPS_PPS_T; + } + + /* In case bitstream read has exceeded the filled size, then + return an error */ + if(EXCEED_OFFSET(ps_bitstrm)) + { + return ERROR_INV_SPS_PPS_T; + } + + ps_subset_sps->s_sps_data.u1_is_valid = 1; + + /* This ensures PPS has valid data in SPS array for reference */ + ps_view_ctxt->ps_sps[ps_subset_sps->s_sps_data.u1_seq_parameter_set_id] = + ps_subset_sps->s_sps_data; + + ps_mvcd_ctxt->u1_num_subset_sps++; + + return OK; +} + +/* This function removes emulation byte "0x03" from bitstream(EBSP to RBSP). + It also converts bytestream format into 32 bit little - endian format. */ +static WORD32 imvcd_transform_nalu(dec_bit_stream_t *ps_bitstrm, UWORD8 *pu1_nal_unit, + UWORD32 u4_numbytes_in_nal_unit) +{ + UWORD32 ui4_word; + UWORD8 u1_cur_byte; + + static const UWORD32 u4_num_bytes_in_word = sizeof(ui4_word) / sizeof(u1_cur_byte); + UWORD32 u4_num_bytes_in_rbsp = 0; + WORD32 i = 0, j; + WORD8 c_count = 0; + UWORD32 *puc_bitstream_buffer = (UWORD32 *) pu1_nal_unit; + UWORD8 u1_nal_header_size = 1; + UWORD8 u1_num_bytes_copied = 0; + + ps_bitstrm->pu4_buffer = puc_bitstream_buffer; + + ui4_word = *pu1_nal_unit++; + u1_num_bytes_copied++; + + if((NAL_UNIT_TYPE(ui4_word) == PREFIX_NAL) || + (NAL_UNIT_TYPE(ui4_word) == CODED_SLICE_EXTENSION)) + { + u1_nal_header_size += 3; + } + + for(j = 0; j < 2; j++) + { + u1_cur_byte = *pu1_nal_unit++; + + ui4_word = ((ui4_word << 8) | u1_cur_byte); + u1_num_bytes_copied++; + + c_count++; + u4_num_bytes_in_rbsp++; + + if(u1_cur_byte != 0x00) + { + c_count = 0; + } + } + + if(u4_numbytes_in_nal_unit > 2) + { + i = ((u4_numbytes_in_nal_unit - 3)); + } + + for(; i > 8; i -= 4) + { + // loop 0 + u1_cur_byte = *pu1_nal_unit++; + + if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && + u1_cur_byte == EMULATION_PREVENTION_BYTE) + { + c_count = 0; + u1_cur_byte = *pu1_nal_unit++; + i--; + } + + ui4_word = ((ui4_word << 8) | u1_cur_byte); + u1_num_bytes_copied++; + if(u4_num_bytes_in_word == u1_num_bytes_copied) + { + *puc_bitstream_buffer = ui4_word; + puc_bitstream_buffer++; + u1_num_bytes_copied = 0; + } + + c_count++; + if(u1_cur_byte != 0x00) c_count = 0; + + // loop 1 + u1_cur_byte = *pu1_nal_unit++; + + if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && + u1_cur_byte == EMULATION_PREVENTION_BYTE) + { + c_count = 0; + u1_cur_byte = *pu1_nal_unit++; + i--; + } + ui4_word = ((ui4_word << 8) | u1_cur_byte); + u1_num_bytes_copied++; + if(u4_num_bytes_in_word == u1_num_bytes_copied) + { + *puc_bitstream_buffer = ui4_word; + puc_bitstream_buffer++; + u1_num_bytes_copied = 0; + } + + c_count++; + if(u1_cur_byte != 0x00) c_count = 0; + + // loop 2 + u1_cur_byte = *pu1_nal_unit++; + + if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && + u1_cur_byte == EMULATION_PREVENTION_BYTE) + { + c_count = 0; + u1_cur_byte = *pu1_nal_unit++; + i--; + } + + ui4_word = ((ui4_word << 8) | u1_cur_byte); + u1_num_bytes_copied++; + if(u4_num_bytes_in_word == u1_num_bytes_copied) + { + *puc_bitstream_buffer = ui4_word; + puc_bitstream_buffer++; + u1_num_bytes_copied = 0; + } + + c_count++; + if(u1_cur_byte != 0x00) c_count = 0; + + // loop 3 + u1_cur_byte = *pu1_nal_unit++; + + if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && + u1_cur_byte == EMULATION_PREVENTION_BYTE) + { + c_count = 0; + u1_cur_byte = *pu1_nal_unit++; + i--; + } + + ui4_word = ((ui4_word << 8) | u1_cur_byte); + u1_num_bytes_copied++; + if(u4_num_bytes_in_word == u1_num_bytes_copied) + { + *puc_bitstream_buffer = ui4_word; + puc_bitstream_buffer++; + u1_num_bytes_copied = 0; + } + + c_count++; + if(u1_cur_byte != 0x00) c_count = 0; + + u4_num_bytes_in_rbsp += 4; + } + + for(; i > 0; i--) + { + u1_cur_byte = *pu1_nal_unit++; + + if(c_count == NUM_OF_ZERO_BYTES_BEFORE_START_CODE && + u1_cur_byte == EMULATION_PREVENTION_BYTE) + { + c_count = 0; + i--; + u1_cur_byte = *pu1_nal_unit++; + } + + ui4_word = ((ui4_word << 8) | u1_cur_byte); + u4_num_bytes_in_rbsp++; + + if((u4_num_bytes_in_rbsp & 0x03) == 0x03) + { + *puc_bitstream_buffer = ui4_word; + puc_bitstream_buffer++; + } + c_count++; + if(u1_cur_byte != 0x00) c_count = 0; + } + + *puc_bitstream_buffer = (ui4_word << ((3 - (((u4_num_bytes_in_rbsp << 30) >> 30))) << 3)); + ps_bitstrm->u4_ofst = 0; + ps_bitstrm->u4_max_ofst = ((u4_num_bytes_in_rbsp + u1_nal_header_size) << 3); + + return (u4_num_bytes_in_rbsp); +} + +WORD32 imvcd_nalu_parser(mvc_dec_ctxt_t *ps_mvcd_ctxt, UWORD8 *pu1_bitstream_buf, + UWORD32 i4_nalu_length) +{ + AVC_EXT_NALU_ID_T e_nalu_id; + + UWORD8 u1_first_byte; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + WORD32 i4_error_code = NOT_OK; + + if((NULL != pu1_bitstream_buf) && (i4_nalu_length > 0)) + { + imvcd_transform_nalu(ps_bitstrm, pu1_bitstream_buf, i4_nalu_length); + + u1_first_byte = ih264d_get_bits_h264(ps_bitstrm, 8); + + if(NAL_FORBIDDEN_BIT(u1_first_byte)) + { + return NOT_OK; + } + + e_nalu_id = NAL_UNIT_TYPE(u1_first_byte); + ps_view_ctxt->u1_nal_unit_type = e_nalu_id; + + // if any other nal unit other than slice nal is encountered in between a + // frame break out of loop without consuming header + if((ps_view_ctxt->u4_slice_start_code_found == 1) && + (ps_view_ctxt->u1_pic_decode_done != 1) && is_slice_nalu_type(e_nalu_id)) + { + return ERROR_INCOMPLETE_FRAME; + } + + switch(e_nalu_id) + { + case PREFIX_NAL: + { + if(!ps_view_ctxt->i4_decode_header) + { + if(1 == ih264d_get_bit_h264(ps_bitstrm)) + { + return IVD_INVALID_BITSTREAM; + } + + i4_error_code = imvcd_nalu_mvc_ext_parser(ps_mvcd_ctxt, ps_bitstrm); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + break; + } + case SUBSET_SPS: + { + ih264d_rbsp_to_sodb(ps_view_ctxt->ps_bitstrm); + + i4_error_code = imvcd_parse_subset_sps(ps_mvcd_ctxt, ps_bitstrm); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + ps_view_ctxt->i4_header_decoded |= 1 << SUBSET_SPS; + + break; + } + case SLICE_NON_IDR: + case SLICE_IDR: + { + if(!ps_view_ctxt->i4_decode_header) + { + if(is_header_decoded(ps_view_ctxt->i4_header_decoded, SPS) && + is_header_decoded(ps_view_ctxt->i4_header_decoded, PPS)) + { + nalu_mvc_ext_t *ps_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + + ps_view_ctxt->u4_slice_start_code_found = 1; + + if((0 == ps_mvcd_ctxt->u2_num_views_decoded) && + !ps_nalu_mvc_ext->u1_inter_view_flag) + { + ps_nalu_mvc_ext->u1_inter_view_flag = 1; + } + + ih264d_rbsp_to_sodb(ps_view_ctxt->ps_bitstrm); + + i4_error_code = imvcd_parse_decode_slice(ps_mvcd_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + else + { + return IVD_INVALID_BITSTREAM; + } + } + + break; + } + case CODED_SLICE_EXTENSION: + { + if(!ps_view_ctxt->i4_decode_header) + { + if(is_header_decoded(ps_view_ctxt->i4_header_decoded, SPS) && + is_header_decoded(ps_view_ctxt->i4_header_decoded, PPS) && + is_header_decoded(ps_view_ctxt->i4_header_decoded, SUBSET_SPS)) + { + ps_view_ctxt->u4_slice_start_code_found = 1; + + if(1 == ih264d_get_bit_h264(ps_bitstrm)) + { + return IVD_INVALID_BITSTREAM; + } + + i4_error_code = imvcd_nalu_mvc_ext_parser(ps_mvcd_ctxt, ps_bitstrm); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ih264d_rbsp_to_sodb(ps_view_ctxt->ps_bitstrm); + + i4_error_code = imvcd_parse_decode_slice(ps_mvcd_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + else + { + return IVD_INVALID_BITSTREAM; + } + } + + break; + } + default: + { + i4_error_code = ERROR_UNKNOWN_NAL; + + break; + } + } + } + + return i4_error_code; +} diff --git a/decoder/mvc/imvcd_nalu_parser.h b/decoder/mvc/imvcd_nalu_parser.h new file mode 100644 index 0000000..1bf2ae4 --- /dev/null +++ b/decoder/mvc/imvcd_nalu_parser.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_nalu_parser.h */ +/* */ +/* Description : Functions for MVC NALU parsing */ +/* */ +/*****************************************************************************/ + +#ifndef _IMVCD_NALU_PARSER_H_ +#define _IMVCD_NALU_PARSER_H_ + +#include "ih264_typedefs.h" +#include "imvcd_structs.h" + +extern WORD32 imvcd_nalu_parser(mvc_dec_ctxt_t *ps_mvcd_ctxt, UWORD8 *pu1_bitstream_buf, + UWORD32 i4_nalu_length); +#endif diff --git a/decoder/mvc/imvcd_slice_functions.c b/decoder/mvc/imvcd_slice_functions.c new file mode 100644 index 0000000..34892d5 --- /dev/null +++ b/decoder/mvc/imvcd_slice_functions.c @@ -0,0 +1,2391 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_slice_functions.c */ +/* */ +/* Description : Functions for MVC Slice parsing, etc. */ +/* */ +/*****************************************************************************/ + +#include "ih264_typedefs.h" +#include "ih264_error.h" +#include "ih264_buf_mgr.h" +#include "ih264d_bitstrm.h" +#include "ih264d_deblocking.h" +#include "ih264d_debug.h" +#include "ih264d_defs.h" +#include "ih264d_error_handler.h" +#include "ih264d_inter_pred.h" +#include "ih264d_mb_utils.h" +#include "ih264d_mvpred.h" +#include "ih264d_parse_slice.h" +#include "ih264d_parse_islice.h" +#include "ih264d_process_bslice.h" +#include "ih264d_process_pslice.h" +#include "ih264d_quant_scaling.h" +#include "ih264d_tables.h" +#include "ih264d_thread_compute_bs.h" +#include "ih264d_thread_parse_decode.h" +#include "ih264d_structs.h" +#include "ih264d_utils.h" +#include "ih264d_api_utils.h" +#include "ithread.h" +#include "imvc_defs.h" +#include "imvcd_dpb_manager.h" +#include "imvcd_error_handler.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +static WORD32 imvcd_set_first_mb_in_slice(dec_struct_t *ps_view_ctxt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + + ps_cur_slice->u2_first_mb_in_slice = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(ps_cur_slice->u2_first_mb_in_slice >= + (ps_view_ctxt->u2_frm_ht_in_mbs * ps_view_ctxt->u2_frm_wd_in_mbs)) + { + return ERROR_CORRUPTED_SLICE; + } + + if(((ps_cur_slice->u2_first_mb_in_slice << ps_cur_slice->u1_mbaff_frame_flag) <= + ps_view_ctxt->u2_cur_mb_addr) && + (ps_view_ctxt->u4_first_slice_in_pic == 0)) + { + return ERROR_CORRUPTED_SLICE; + } + + COPYTHECONTEXT("SH: first_mb_in_slice", ps_cur_slice->u2_first_mb_in_slice); + + return OK; +} + +static WORD32 imvcd_set_slice_type(dec_struct_t *ps_view_ctxt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + + ps_cur_slice->u1_slice_type = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(ps_cur_slice->u1_slice_type > 9) + { + return ERROR_INV_SLC_TYPE_T; + } + + if(ps_cur_slice->u1_slice_type > 4) + { + ps_cur_slice->u1_slice_type -= 5; + } + + COPYTHECONTEXT("SH: slice_type", ps_cur_slice->u1_slice_type); + + return OK; +} + +static WORD32 imvcd_set_cur_pps(dec_struct_t *ps_view_ctxt, UWORD8 *pu1_pps_id) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pu1_pps_id[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + ps_view_ctxt->ps_cur_pps = &ps_view_ctxt->ps_pps[pu1_pps_id[0]]; + ps_view_ctxt->ps_cur_sps = ps_view_ctxt->ps_pps[pu1_pps_id[0]].ps_sps; + + if(!ps_view_ctxt->ps_cur_pps->u1_is_valid || !ps_view_ctxt->ps_cur_pps->ps_sps->u1_is_valid) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: pps_id", pu1_pps_id[0]); + + return OK; +} + +static WORD32 imvcd_set_frame_num(dec_struct_t *ps_view_ctxt, UWORD8 u1_bits_in_frm_num) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + + ps_cur_slice->u2_frame_num = ih264d_get_bits_h264(ps_bitstrm, u1_bits_in_frm_num); + + COPYTHECONTEXT("SH: frame_num", ps_cur_slice->u2_frame_num); + + return OK; +} + +static WORD32 imvcd_set_idr_pic_id(dec_struct_t *ps_view_ctxt, UWORD32 *pu4_idr_pic_id) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pu4_idr_pic_id[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(pu4_idr_pic_id[0] > 65535) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: idr_pic_id", pu4_idr_pic_id[0]); + + return OK; +} + +static WORD32 imvcd_set_poc_lsb(dec_struct_t *ps_view_ctxt, WORD32 *pi4_pic_order_cnt_lsb, + WORD32 i4_max_poc_lsb, UWORD8 u1_log2_max_poc_lsb) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pi4_pic_order_cnt_lsb[0] = ih264d_get_bits_h264(ps_bitstrm, u1_log2_max_poc_lsb); + + if((pi4_pic_order_cnt_lsb[0] < 0) || (pi4_pic_order_cnt_lsb[0] > i4_max_poc_lsb)) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: pic_order_cnt_lsb", pi4_pic_order_cnt_lsb[0]); + + return OK; +} + +static WORD32 imvcd_set_delta_poc(dec_struct_t *ps_view_ctxt, WORD32 *pi4_delta_poc) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pi4_delta_poc[0] = ih264d_sev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + COPYTHECONTEXT("SH: delta_pic_order_cnt", pi4_delta_poc[0]); + + return OK; +} + +static WORD32 imvcd_set_redundant_pic_cnt(dec_struct_t *ps_view_ctxt, UWORD8 *pu1_redundant_pic_cnt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pu1_redundant_pic_cnt[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(pu1_redundant_pic_cnt[0] > MAX_REDUNDANT_PIC_CNT) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: redundant_pic_cnt", pu1_redundant_pic_cnt[0]); + + return OK; +} + +static WORD32 imvcd_set_direct_spatial_mv_pred_flag(dec_struct_t *ps_view_ctxt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + + ps_cur_slice->u1_direct_spatial_mv_pred_flag = ih264d_get_bit_h264(ps_bitstrm); + + COPYTHECONTEXT("SH: direct_spatial_mv_pred_flag", ps_cur_slice->u1_direct_spatial_mv_pred_flag); + + return OK; +} + +static WORD32 imvcd_set_ref_idx_override_flag(dec_struct_t *ps_view_ctxt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + + ps_cur_slice->u1_num_ref_idx_active_override_flag = ih264d_get_bit_h264(ps_bitstrm); + + COPYTHECONTEXT("SH: num_ref_idx_override_flag", + ps_cur_slice->u1_num_ref_idx_active_override_flag); + + return OK; +} + +static WORD32 imvcd_set_num_ref_idx_active(dec_struct_t *ps_view_ctxt, UWORD8 *pu1_num_ref_idx) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pu1_num_ref_idx[0] = 1 + ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(pu1_num_ref_idx[0] > H264_MAX_REF_PICS) + { + return ERROR_NUM_REF; + } + + COPYTHECONTEXT("SH: num_ref_idx_lx_active_minus1", pu1_num_ref_idx[0] - 1); + + return OK; +} + +static WORD32 imvcd_set_ref_pic_list_reordering_flag(dec_struct_t *ps_view_ctxt, + UWORD8 *pu1_ref_idx_reorder_flag) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pu1_ref_idx_reorder_flag[0] = ih264d_get_bit_h264(ps_bitstrm); + + COPYTHECONTEXT("SH: ref_pic_list_reordering_flag_lx", pu1_ref_idx_reorder_flag[0]); + + return OK; +} + +static WORD32 imvcd_set_modification_of_pic_nums_idc(dec_struct_t *ps_view_ctxt, + UWORD8 *pu1_modification_of_pic_nums_idc) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pu1_modification_of_pic_nums_idc[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + COPYTHECONTEXT("SH: modification_of_pic_nums_idc", pu1_modification_of_pic_nums_idc[0]); + + return OK; +} + +static WORD32 imvcd_set_abs_diff_pic_num_minus1(dec_struct_t *ps_view_ctxt, + WORD32 *pi4_abs_diff_pic_num_minus1) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pi4_abs_diff_pic_num_minus1[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + COPYTHECONTEXT("SH: abs_diff_pic_num_minus1", pi4_abs_diff_pic_num_minus1[0]); + + return OK; +} + +static WORD32 imvcd_set_abs_diff_view_idx_minus1(dec_struct_t *ps_view_ctxt, + WORD32 *pi4_abs_diff_view_idx_minus1) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pi4_abs_diff_view_idx_minus1[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + COPYTHECONTEXT("SH: abs_diff_view_idx_minus1", pi4_abs_diff_view_idx_minus1[0]); + + return OK; +} + +static WORD32 imvcd_set_long_term_pic_num(dec_struct_t *ps_view_ctxt, WORD32 *pi4_long_term_pic_num) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + pi4_long_term_pic_num[0] = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + COPYTHECONTEXT("SH: long_term_pic_num", pi4_long_term_pic_num[0]); + + return OK; +} + +static WORD32 imvcd_set_cabac_init_idc(dec_struct_t *ps_view_ctxt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + + ps_cur_slice->u1_cabac_init_idc = ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(ps_cur_slice->u1_cabac_init_idc > MAX_CABAC_INIT_IDC) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: cabac_init_idc", ps_cur_slice->u1_cabac_init_idc); + + return OK; +} + +static WORD32 imvcd_set_slice_qp(dec_struct_t *ps_view_ctxt) +{ + WORD8 i1_slice_qp_delta; + + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + dec_pic_params_t *ps_cur_pps = ps_view_ctxt->ps_cur_pps; + + i1_slice_qp_delta = ih264d_sev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + ps_cur_slice->u1_slice_qp = i1_slice_qp_delta + ps_cur_pps->u1_pic_init_qp; + + if(ps_cur_slice->u1_slice_qp > MAX_H264_QP) + { + return ERROR_INV_RANGE_QP_T; + } + + COPYTHECONTEXT("SH: slice_qp_delta", i1_slice_qp_delta); + + return OK; +} + +static WORD32 imvcd_set_slice_deblk_params(dec_struct_t *ps_view_ctxt) +{ + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + dec_pic_params_t *ps_cur_pps = ps_view_ctxt->ps_cur_pps; + + if(ps_cur_pps->u1_deblocking_filter_parameters_present_flag) + { + ps_cur_slice->u1_disable_dblk_filter_idc = + ih264d_uev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer); + + if(ps_cur_slice->u1_disable_dblk_filter_idc > SLICE_BOUNDARY_DBLK_DISABLED) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: disable_deblocking_filter_idc", + ps_cur_slice->u1_disable_dblk_filter_idc); + + if(ps_cur_slice->u1_disable_dblk_filter_idc != 1) + { + ps_cur_slice->i1_slice_alpha_c0_offset = + ih264d_sev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer) << 1; + + if((MIN_DBLK_FIL_OFF > ps_cur_slice->i1_slice_alpha_c0_offset) || + (ps_cur_slice->i1_slice_alpha_c0_offset > MAX_DBLK_FIL_OFF)) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: slice_alpha_c0_offset_div2", + ps_cur_slice->i1_slice_alpha_c0_offset >> 1); + + ps_cur_slice->i1_slice_beta_offset = + ih264d_sev(&ps_bitstrm->u4_ofst, ps_bitstrm->pu4_buffer) << 1; + + if((MIN_DBLK_FIL_OFF > ps_cur_slice->i1_slice_beta_offset) || + (ps_cur_slice->i1_slice_beta_offset > MAX_DBLK_FIL_OFF)) + { + return ERROR_INV_SLICE_HDR_T; + } + + COPYTHECONTEXT("SH: slice_beta_offset_div2", ps_cur_slice->i1_slice_beta_offset >> 1); + } + else + { + ps_cur_slice->i1_slice_alpha_c0_offset = 0; + ps_cur_slice->i1_slice_beta_offset = 0; + } + } + else + { + ps_cur_slice->u1_disable_dblk_filter_idc = 0; + ps_cur_slice->i1_slice_alpha_c0_offset = 0; + ps_cur_slice->i1_slice_beta_offset = 0; + } + + return OK; +} + +static WORD32 imvcd_set_ref_pic_list_mod_data(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i4_error_code; + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + ref_pic_list_mod_data_t *ps_ref_pic_list_mod_data = + imvcd_get_cur_ref_pic_list_mod_data(ps_mvcd_ctxt); + + bool b_is_b_pic = ps_cur_slice->u1_slice_type == BSLICE; + + for(i = 0; i < 1 + ((WORD32) b_is_b_pic); i++) + { + ps_ref_pic_list_mod_data->au1_num_active_refs[i] = + ps_cur_slice->u1_num_ref_idx_lx_active[i]; + + i4_error_code = imvcd_set_ref_pic_list_reordering_flag( + ps_view_ctxt, &ps_ref_pic_list_mod_data->au1_ref_pic_list_modification_flag_lx[i]); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(ps_ref_pic_list_mod_data->au1_ref_pic_list_modification_flag_lx[i]) + { + UWORD8 *pu1_modification_of_pic_nums_idc = + ps_ref_pic_list_mod_data->au1_modification_of_pic_nums_idc[i]; + WORD32 *pi4_abs_diff_pic_num_minus1 = + ps_ref_pic_list_mod_data->ai4_abs_diff_pic_num_minus1[i]; + WORD32 *pi4_long_term_pic_num = ps_ref_pic_list_mod_data->ai4_long_term_pic_num[i]; + WORD32 *pi4_abs_diff_view_idx_minus1 = + ps_ref_pic_list_mod_data->ai4_abs_diff_view_idx_minus1[i]; + + do + { + i4_error_code = imvcd_set_modification_of_pic_nums_idc( + ps_view_ctxt, pu1_modification_of_pic_nums_idc); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if((0 == pu1_modification_of_pic_nums_idc[0]) || + (1 == pu1_modification_of_pic_nums_idc[0])) + { + i4_error_code = imvcd_set_abs_diff_pic_num_minus1(ps_view_ctxt, + pi4_abs_diff_pic_num_minus1); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + else if(2 == pu1_modification_of_pic_nums_idc[0]) + { + i4_error_code = + imvcd_set_long_term_pic_num(ps_view_ctxt, pi4_long_term_pic_num); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + else if((4 == pu1_modification_of_pic_nums_idc[0]) || + (5 == pu1_modification_of_pic_nums_idc[0])) + { + i4_error_code = imvcd_set_abs_diff_view_idx_minus1( + ps_view_ctxt, pi4_abs_diff_view_idx_minus1); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + else if(3 != pu1_modification_of_pic_nums_idc[0]) + { + return ERROR_REFIDX_ORDER_T; + } + else + { + break; + } + + pu1_modification_of_pic_nums_idc++; + pi4_abs_diff_pic_num_minus1++; + pi4_long_term_pic_num++; + pi4_abs_diff_view_idx_minus1++; + } while(true); + } + } + + return OK; +} + +static WORD32 imvcd_decode_gaps_in_frame_num(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + pocstruct_t s_tmp_poc; + + UWORD32 u4_start_frm_num; + WORD32 i4_poc; + WORD8 i1_gap_idx; + WORD8 *pi1_gaps_per_seq; + WORD32 i4_error_code; + WORD64 i8_display_poc; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + dec_pic_params_t *ps_pps = ps_view_ctxt->ps_cur_pps; + mvc_dpb_manager_t *ps_dpb_mgr = ps_mvcd_ctxt->ps_dpb_mgr; + + UWORD16 u2_frame_num = ps_cur_slice->u2_frame_num; + WORD32 i4_frame_gaps = 0; + UWORD32 u4_next_frm_num = ps_view_ctxt->u2_prev_ref_frame_num + 1; + UWORD32 u4_max_frm_num = ps_view_ctxt->ps_cur_sps->u2_u4_max_pic_num_minus1 + 1; + WORD32 *pi4_gaps_start_frm_num = ps_dpb_mgr->ai4_gaps_start_frm_num; + bool b_is_idr_slice = imvcd_is_idr_au(ps_mvcd_ctxt); + + if(ps_cur_slice->u1_field_pic_flag) + { + if(ps_view_ctxt->u2_prev_ref_frame_num == u2_frame_num) + { + return OK; + } + } + + if(u4_next_frm_num >= u4_max_frm_num) + { + u4_next_frm_num -= u4_max_frm_num; + } + + if(u4_next_frm_num == u2_frame_num) + { + return OK; + } + + if(b_is_idr_slice && (u4_next_frm_num >= u2_frame_num)) + { + return OK; + } + + u4_start_frm_num = u4_next_frm_num; + + s_tmp_poc.i4_pic_order_cnt_lsb = 0; + s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0; + s_tmp_poc.i4_pic_order_cnt_lsb = 0; + s_tmp_poc.i4_delta_pic_order_cnt_bottom = 0; + s_tmp_poc.i4_delta_pic_order_cnt[0] = 0; + s_tmp_poc.i4_delta_pic_order_cnt[1] = 0; + + for(i1_gap_idx = 0; i1_gap_idx < MAX_FRAMES; i1_gap_idx++) + { + if(INVALID_FRAME_NUM == pi4_gaps_start_frm_num[i1_gap_idx]) + { + break; + } + } + + if(MAX_FRAMES == i1_gap_idx) + { + return ERROR_DBP_MANAGER_T; + } + + i4_poc = 0; + pi4_gaps_start_frm_num[i1_gap_idx] = u4_start_frm_num; + ps_dpb_mgr->ai4_gaps_end_frm_num[i1_gap_idx] = u2_frame_num - 1; + pi1_gaps_per_seq = ps_dpb_mgr->ai1_gaps_per_seq; + pi1_gaps_per_seq[i1_gap_idx] = 0; + + while(u4_next_frm_num != u2_frame_num) + { + imvcd_dpb_delete_nonref_nondisplay_pics(ps_dpb_mgr); + + if(ps_pps->ps_sps->u1_pic_order_cnt_type) + { + /* allocate a picture buffer and insert it as ST node */ + i4_error_code = + ih264d_decode_pic_order_cnt(0, u4_next_frm_num, &ps_view_ctxt->s_prev_pic_poc, + &s_tmp_poc, ps_cur_slice, ps_pps, 1, 0, 0, &i4_poc); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + /* Display seq no calculations */ + if(i4_poc >= ps_view_ctxt->i4_max_poc) + { + ps_view_ctxt->i4_max_poc = i4_poc; + } + + /* IDR Picture or POC wrap around */ + if(i4_poc == 0) + { + imvcd_modulate_max_disp_seq(ps_view_ctxt); + } + + ps_cur_slice->u1_mmco_equalto5 = 0; + ps_cur_slice->u2_frame_num = u4_next_frm_num; + } + + if(ps_dpb_mgr->i1_poc_buf_id_entries >= ps_view_ctxt->u1_max_dec_frame_buffering) + { + i4_error_code = imvcd_dpb_assign_display_seq(ps_mvcd_ctxt->ps_dpb_mgr); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + i8_display_poc = ps_view_ctxt->i4_prev_max_display_seq + i4_poc; + + if(IS_OUT_OF_RANGE_S32(i8_display_poc)) + { + ps_view_ctxt->i4_prev_max_display_seq = 0; + } + + i4_error_code = imvcd_dpb_insert_pic_in_display_list( + ps_dpb_mgr, ps_view_ctxt->i4_prev_max_display_seq + i4_poc, u4_next_frm_num, + DO_NOT_DISP); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + pi1_gaps_per_seq[i1_gap_idx]++; + + i4_error_code = + imvcd_dpb_do_mmco_for_gaps(ps_dpb_mgr, ps_view_ctxt->ps_cur_sps->u1_num_ref_frames); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + imvcd_dpb_delete_nonref_nondisplay_pics(ps_dpb_mgr); + + u4_next_frm_num++; + + if(u4_next_frm_num >= u4_max_frm_num) + { + u4_next_frm_num -= u4_max_frm_num; + } + + i4_frame_gaps++; + } + + return OK; +} + +static void imvcd_pocstruct_init(dec_struct_t *ps_view_ctxt) +{ + pocstruct_t *ps_prev_poc = &ps_view_ctxt->s_prev_pic_poc; + pocstruct_t *ps_cur_poc = &ps_view_ctxt->s_cur_pic_poc; + + ps_prev_poc->i4_prev_frame_num_ofst = ps_cur_poc->i4_prev_frame_num_ofst; + ps_prev_poc->u2_frame_num = ps_cur_poc->u2_frame_num; + ps_prev_poc->u1_mmco_equalto5 = ps_cur_poc->u1_mmco_equalto5; + + if(ps_view_ctxt->ps_cur_slice->u1_nal_ref_idc) + { + ps_prev_poc->i4_pic_order_cnt_lsb = ps_cur_poc->i4_pic_order_cnt_lsb; + ps_prev_poc->i4_pic_order_cnt_msb = ps_cur_poc->i4_pic_order_cnt_msb; + ps_prev_poc->i4_delta_pic_order_cnt_bottom = ps_cur_poc->i4_delta_pic_order_cnt_bottom; + ps_prev_poc->i4_delta_pic_order_cnt[0] = ps_cur_poc->i4_delta_pic_order_cnt[0]; + ps_prev_poc->i4_delta_pic_order_cnt[1] = ps_cur_poc->i4_delta_pic_order_cnt[1]; + ps_prev_poc->u1_bot_field = ps_cur_poc->u1_bot_field; + } +} + +static WORD32 imvcd_pic_init(mvc_dec_ctxt_t *ps_mvcd_ctxt, pocstruct_t *ps_cur_poc, WORD32 i4_poc, + bool b_is_idr_slice) +{ + WORD32 i4_error_code; + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + pocstruct_t *ps_prev_poc = &ps_view_ctxt->s_cur_pic_poc; + dec_slice_params_t *ps_cur_slice = ps_view_ctxt->ps_cur_slice; + dec_pic_params_t *ps_pps = ps_view_ctxt->ps_cur_pps; + dec_seq_params_t *ps_sps = ps_pps->ps_sps; + subset_sps_t *ps_subset_sps = imvcd_get_valid_subset_sps(ps_mvcd_ctxt); + nalu_mvc_ext_t *ps_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + dec_err_status_t *ps_err = ps_view_ctxt->ps_dec_err_status; + prev_seq_params_t *ps_prev_seq_params = &ps_view_ctxt->s_prev_seq_params; + + UWORD16 u2_num_views = ps_mvcd_ctxt->u2_num_views; + UWORD16 u2_view_order_id = ps_mvcd_ctxt->u2_num_views_decoded; + UWORD16 u2_view_id = ps_nalu_mvc_ext->u2_view_id; + UWORD16 u2_frame_num = ps_cur_slice->u2_frame_num; + + ps_prev_poc->i4_pic_order_cnt_lsb = ps_cur_poc->i4_pic_order_cnt_lsb; + ps_prev_poc->i4_pic_order_cnt_msb = ps_cur_poc->i4_pic_order_cnt_msb; + ps_prev_poc->i4_delta_pic_order_cnt_bottom = ps_cur_poc->i4_delta_pic_order_cnt_bottom; + ps_prev_poc->i4_delta_pic_order_cnt[0] = ps_cur_poc->i4_delta_pic_order_cnt[0]; + ps_prev_poc->i4_delta_pic_order_cnt[1] = ps_cur_poc->i4_delta_pic_order_cnt[1]; + ps_prev_poc->u1_bot_field = ps_view_ctxt->ps_cur_slice->u1_bottom_field_flag; + ps_prev_poc->i4_prev_frame_num_ofst = ps_cur_poc->i4_prev_frame_num_ofst; + ps_prev_poc->u2_frame_num = u2_frame_num; + + ps_view_ctxt->i1_prev_mb_qp_delta = 0; + ps_view_ctxt->i1_next_ctxt_idx = 0; + ps_view_ctxt->u4_use_intrapred_line_copy = 1; + + if(ps_view_ctxt->u4_num_cores == 1) + { + ps_view_ctxt->u4_nmb_deblk = 1; + } + else + { + ps_view_ctxt->u4_nmb_deblk = 0; + } + + ps_view_ctxt->u4_app_disable_deblk_frm = 0; + if(ps_view_ctxt->i4_degrade_type && ps_view_ctxt->i4_degrade_pics) + { + WORD32 i4_degrade_pic = 0; + + ps_view_ctxt->i4_degrade_pic_cnt++; + + /* If degrade is to be done in all frames, then do not check further */ + switch(ps_view_ctxt->i4_degrade_pics) + { + case 4: + { + i4_degrade_pic = 1; + + break; + } + case 3: + { + if(ps_cur_slice->u1_slice_type != I_SLICE) + { + i4_degrade_pic = 1; + } + + break; + } + case 2: + { + if((ps_cur_slice->u1_slice_type != I_SLICE) && + (ps_view_ctxt->i4_degrade_pic_cnt != ps_view_ctxt->i4_nondegrade_interval)) + { + i4_degrade_pic = 1; + } + + break; + } + case 1: + { + if(0 == ps_cur_slice->u1_nal_ref_idc) + { + i4_degrade_pic = 1; + } + + break; + } + } + + if(i4_degrade_pic) + { + if(ps_view_ctxt->i4_degrade_type & 0x2) + { + ps_view_ctxt->u4_app_disable_deblk_frm = 1; + } + + if(0 == ps_cur_slice->u1_nal_ref_idc) + { + if(ps_view_ctxt->i4_degrade_type & 0x4) + { + ps_view_ctxt->i4_mv_frac_mask = 0; + } + + if(ps_view_ctxt->i4_degrade_type & 0x8) + { + ps_view_ctxt->i4_mv_frac_mask = 0; + } + } + } + else + { + ps_view_ctxt->i4_degrade_pic_cnt = 0; + } + } + + if((ps_cur_slice->u1_slice_type == I_SLICE) || (ps_cur_slice->u1_slice_type == SI_SLICE)) + { + ps_err->u1_cur_pic_type = PIC_TYPE_I; + } + else + { + ps_err->u1_cur_pic_type = PIC_TYPE_UNKNOWN; + } + + if(ps_err->u1_pic_aud_i == PIC_TYPE_I) + { + ps_err->u1_cur_pic_type = PIC_TYPE_I; + ps_err->u1_pic_aud_i = PIC_TYPE_UNKNOWN; + } + + if(b_is_idr_slice) + { + if(ps_err->u1_err_flag) + { + imvcd_reset_dpb(ps_mvcd_ctxt->ps_dpb_mgr); + } + + ps_err->u1_err_flag = ACCEPT_ALL_PICS; + } + + if(ps_view_ctxt->u1_init_dec_flag && ps_view_ctxt->s_prev_seq_params.u1_eoseq_pending && + (u2_view_order_id == (u2_num_views - 1))) + { + imvcd_release_all_ref_and_io_bufs(ps_mvcd_ctxt, MAX_DISP_BUFS_NEW); + + ps_view_ctxt->u1_second_field = 0; + ps_view_ctxt->i4_cur_display_seq = 0; + ps_view_ctxt->s_prev_seq_params.u1_eoseq_pending = 0; + + imvcd_dpb_set_display_num(ps_mvcd_ctxt->ps_dpb_mgr, 0); + } + + if(0 == u2_view_order_id) + { + imvcd_dpb_set_max_pic_num(ps_mvcd_ctxt->ps_dpb_mgr, ps_sps->u2_u4_max_pic_num_minus1 + 1); + imvcd_dpb_set_num_views(ps_mvcd_ctxt->ps_dpb_mgr, u2_num_views); + } + + ps_view_ctxt->i4_pic_type = NA_SLICE; + ps_view_ctxt->i4_frametype = IV_NA_FRAME; + ps_view_ctxt->i4_content_type = IV_CONTENTTYPE_NA; + + ps_sps->u2_max_mb_addr = ps_sps->u2_frm_wd_in_mbs * ps_sps->u2_frm_ht_in_mbs - 1; + ps_view_ctxt->u2_frm_ht_in_mbs = ps_sps->u2_frm_ht_in_mbs; + + if(!ps_view_ctxt->u1_init_dec_flag) + { + ps_view_ctxt->u1_max_dec_frame_buffering = ih264d_get_dpb_size(ps_sps); + + ps_view_ctxt->i4_display_delay = ps_view_ctxt->u1_max_dec_frame_buffering; + + if(ps_sps->u1_vui_parameters_present_flag && ps_sps->s_vui.u1_bitstream_restriction_flag) + { + if(ps_sps->u1_frame_mbs_only_flag) + { + ps_view_ctxt->i4_display_delay = ps_sps->s_vui.u4_num_reorder_frames + 1; + } + else + { + ps_view_ctxt->i4_display_delay = ps_sps->s_vui.u4_num_reorder_frames * 2 + 2; + } + } + + if(IVD_DECODE_FRAME_OUT == ps_view_ctxt->e_frm_out_mode) + { + ps_view_ctxt->i4_display_delay = 0; + } + + imvcd_dpb_set_display_delay(ps_mvcd_ctxt->ps_dpb_mgr, ps_view_ctxt->i4_display_delay); + + ps_view_ctxt->u1_pic_bufs = ps_view_ctxt->i4_display_delay + ps_sps->u1_num_ref_frames + 1; + ps_view_ctxt->u1_pic_bufs += imvcd_get_max_num_ivp_refs(ps_mvcd_ctxt); + ps_view_ctxt->u1_pic_bufs = CLIP3(2, MVC_MAX_REF_PICS, ps_view_ctxt->u1_pic_bufs); + + ps_view_ctxt->u1_max_dec_frame_buffering = + MIN(ps_view_ctxt->u1_max_dec_frame_buffering, ps_view_ctxt->u1_pic_bufs); + + /*********************************************************************/ + /* Configuring decoder parameters based on level and then */ + /* fresh pointer initialisation in decoder scratch and state buffers */ + /*********************************************************************/ + i4_error_code = ih264d_init_dec_mb_grp(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + i4_error_code = imvcd_allocate_dynamic_bufs(ps_mvcd_ctxt); + + if(i4_error_code != OK) + { + imvcd_free_dynamic_bufs(ps_mvcd_ctxt); + + return IVD_MEM_ALLOC_FAILED; + } + + i4_error_code = imvcd_init_au_buffers(ps_mvcd_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + i4_error_code = imvcd_init_au_mv_pred_bufs(ps_mvcd_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ps_view_ctxt->u1_init_dec_flag = 1; + ps_prev_seq_params->u2_frm_wd_in_mbs = ps_sps->u2_frm_wd_in_mbs; + ps_prev_seq_params->u1_level_idc = ps_sps->u1_level_idc; + ps_prev_seq_params->u1_profile_idc = ps_sps->u1_profile_idc; + ps_prev_seq_params->u2_frm_ht_in_mbs = ps_sps->u2_frm_ht_in_mbs; + ps_prev_seq_params->u1_frame_mbs_only_flag = ps_sps->u1_frame_mbs_only_flag; + ps_prev_seq_params->u1_direct_8x8_inference_flag = ps_sps->u1_direct_8x8_inference_flag; + + ps_view_ctxt->i4_cur_display_seq = 0; + ps_view_ctxt->i4_prev_max_display_seq = 0; + ps_view_ctxt->i4_max_poc = 0; + + imvcd_dpb_set_display_num(ps_mvcd_ctxt->ps_dpb_mgr, 0); + + { + /* 0th entry of CtxtIncMbMap will be always be containing default values + for CABAC context representing MB not available */ + ctxt_inc_mb_info_t *p_DefCtxt = ps_view_ctxt->p_ctxt_inc_mb_map - 1; + UWORD8 *pu1_temp; + + p_DefCtxt->u1_mb_type = CAB_SKIP; + + p_DefCtxt->u1_cbp = 0x0f; + p_DefCtxt->u1_intra_chroma_pred_mode = 0; + + p_DefCtxt->u1_yuv_dc_csbp = 0x7; + + p_DefCtxt->u1_transform8x8_ctxt = 0; + + pu1_temp = (UWORD8 *) p_DefCtxt->i1_ref_idx; + for(i = 0; i < 4; i++, pu1_temp++) + { + (*pu1_temp) = 0; + } + + pu1_temp = (UWORD8 *) p_DefCtxt->u1_mv; + for(i = 0; i < 16; i++, pu1_temp++) + { + (*pu1_temp) = 0; + } + + ps_view_ctxt->ps_def_ctxt_mb_info = p_DefCtxt; + } + } + + /* reset DBP commands read u4_flag */ + ps_view_ctxt->ps_dpb_cmds->u1_dpb_commands_read = 0; + + ps_view_ctxt->pv_parse_tu_coeff_data = ps_view_ctxt->pv_pic_tu_coeff_data; + ps_view_ctxt->pv_proc_tu_coeff_data = ps_view_ctxt->pv_pic_tu_coeff_data; + ps_view_ctxt->ps_nmb_info = ps_view_ctxt->ps_frm_mb_info; + + if(ps_view_ctxt->u1_separate_parse) + { + UWORD32 num_mbs; + + num_mbs = ps_view_ctxt->ps_cur_sps->u2_total_num_of_mbs; + + if(ps_view_ctxt->pu1_dec_mb_map) + { + memset((void *) ps_view_ctxt->pu1_dec_mb_map, 0, num_mbs); + } + + if(ps_view_ctxt->pu1_recon_mb_map) + { + memset((void *) ps_view_ctxt->pu1_recon_mb_map, 0, num_mbs); + } + + if(ps_view_ctxt->pu2_slice_num_map) + { + memset((void *) ps_view_ctxt->pu2_slice_num_map, 0, (num_mbs * sizeof(UWORD16))); + } + } + + ps_view_ctxt->ps_parse_cur_slice = &(ps_view_ctxt->ps_dec_slice_buf[0]); + ps_view_ctxt->ps_decode_cur_slice = &(ps_view_ctxt->ps_dec_slice_buf[0]); + ps_view_ctxt->ps_computebs_cur_slice = &(ps_view_ctxt->ps_dec_slice_buf[0]); + ps_view_ctxt->u2_cur_slice_num = 0; + + ps_view_ctxt->s_high_profile.u1_scaling_present = 0; + ps_view_ctxt->s_high_profile.u1_transform8x8_present = 0; + + if(0 == u2_view_order_id) + { + mvc_au_buffer_t *ps_cur_au; + mvc_au_mv_pred_t *ps_au_mv_data; + + WORD32 i4_pic_buf_id, i4_mv_buf_id; + + ps_cur_au = (mvc_au_buffer_t *) ih264_buf_mgr_get_next_free( + ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, &i4_pic_buf_id); + + if(NULL == ps_cur_au) + { + return ERROR_UNAVAIL_PICBUF_T; + } + else + { + /* Buf will alwys be marked as REF here to ensure IVP works */ + /* If AU nalRefIdc=0, REF status will be removed during endOfAU processing + */ + ih264_buf_mgr_set_status(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, i4_pic_buf_id, + BUF_MGR_IO | BUF_MGR_REF); + } + + ps_au_mv_data = (mvc_au_mv_pred_t *) ih264_buf_mgr_get_next_free( + ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, &i4_mv_buf_id); + + if(ps_au_mv_data == NULL) + { + return ERROR_UNAVAIL_MVBUF_T; + } + else + { + /* Buf will alwys be marked as REF here to ensure IVP works */ + /* If AU nalRefIdc=0, REF status will be removed during endOfAU processing + */ + ih264_buf_mgr_set_status(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, + i4_mv_buf_id, BUF_MGR_REF); + } + + ps_mvcd_ctxt->ps_cur_au = ps_cur_au; + + ps_cur_au->s_sei_pic = ps_view_ctxt->ps_sei[0]; + + ps_cur_au->i4_mv_buf_id = i4_mv_buf_id; + ps_cur_au->ps_au_mv_data = ps_au_mv_data; + ps_cur_au->i4_poc = i4_poc; + ps_cur_au->i4_avg_poc = i4_poc; + ps_cur_au->i4_frame_num = u2_frame_num; + ps_cur_au->i4_pic_num = u2_frame_num; + ps_cur_au->u4_time_stamp = ps_view_ctxt->u4_ts; + ps_cur_au->u1_picturetype = FRM_PIC; + ps_cur_au->u2_disp_width = ps_view_ctxt->u2_disp_width; + ps_cur_au->u2_disp_height = ps_view_ctxt->u2_disp_height; + + memset(ps_cur_au->au4_pack_slc_typ, 0, sizeof(ps_cur_au->au4_pack_slc_typ)); + + ps_mvcd_ctxt->s_mvc_au_buf_mgr.au1_au_buf_id_to_mv_buf_id_map[i4_pic_buf_id] = i4_mv_buf_id; + ps_mvcd_ctxt->s_mvc_au_buf_mgr.aps_buf_id_to_au_buf_map[i4_pic_buf_id] = ps_cur_au; + ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.aps_buf_id_to_mv_pred_buf_map[i4_mv_buf_id] = + ps_au_mv_data; + + ps_view_ctxt->au1_pic_buf_ref_flag[i4_pic_buf_id] = 0; + + ps_cur_au->s_ivp_data.b_is_ivp_ref = false; + + imvcd_dpb_init_au_bufs(ps_mvcd_ctxt->ps_dpb_mgr, ps_cur_au); + } + + if(u2_view_order_id > 0) + { + ps_mvcd_ctxt->ps_cur_au->as_disp_offsets[u2_view_id] = + ps_mvcd_ctxt->aps_pps_id_to_subset_sps_map[ps_pps->u1_pic_parameter_set_id] + ->s_disp_offsets; + } + else + { + /* Accounting for lihbavc's idiocy */ + ps_mvcd_ctxt->ps_cur_au->as_disp_offsets[u2_view_id].u2_left_offset = + ps_view_ctxt->u2_crop_offset_y; + ps_mvcd_ctxt->ps_cur_au->as_disp_offsets[u2_view_id].u2_right_offset = 0; + ps_mvcd_ctxt->ps_cur_au->as_disp_offsets[u2_view_id].u2_top_offset = 0; + ps_mvcd_ctxt->ps_cur_au->as_disp_offsets[u2_view_id].u2_bottom_offset = 0; + } + + for(i = 0; i < 2; i++) + { + ps_view_ctxt->ps_ref_pic_buf_lx[i] = imvcd_dpb_get_view_ref_pic_list( + ps_mvcd_ctxt->ps_dpb_mgr, u2_view_order_id, u2_view_id, i); + + imvcd_set_view_buf_id_to_buf_map(ps_view_ctxt); + } + + if(ps_mvcd_ctxt->u2_num_views > 1) + { + imvcd_dpb_init_view_bufs(ps_mvcd_ctxt->ps_dpb_mgr, u2_view_order_id, u2_view_id); + + imvcd_dpb_init_ivp_ctxt(ps_mvcd_ctxt->ps_dpb_mgr, &ps_subset_sps->s_sps_mvc_ext, + ps_mvcd_ctxt->as_nalu_mvc_ext); + } + + ps_view_ctxt->u4_pic_buf_got = 1; + ps_cur_slice->u1_mbaff_frame_flag = 0; + + ps_view_ctxt->ps_cur_mb_row = ps_view_ctxt->ps_nbr_mb_row; + // Increment by 2 ,so that left mb (mbaff decrements by 2) will always be + // valid + ps_view_ctxt->ps_cur_mb_row += 2; + ps_view_ctxt->ps_top_mb_row = ps_view_ctxt->ps_nbr_mb_row; + ps_view_ctxt->ps_top_mb_row += ps_view_ctxt->u2_frm_wd_in_mbs + 2; + // Increment by 2 ,so that left mb (mbaff decrements by 2) will always be + // valid + ps_view_ctxt->ps_top_mb_row += 2; + ps_view_ctxt->u1_mb_idx = 0; + ps_view_ctxt->u2_total_mbs_coded = 0; + ps_view_ctxt->i4_submb_ofst = -(SUB_BLK_SIZE); + ps_view_ctxt->i2_prev_slice_mbx = -1; + ps_view_ctxt->i2_prev_slice_mby = 0; + + ps_view_ctxt->u4_pred_info_idx = 0; + ps_view_ctxt->u4_pred_info_pkd_idx = 0; + ps_view_ctxt->ps_part = ps_view_ctxt->ps_parse_part_params; + + ps_view_ctxt->u4_dma_buf_idx = 0; + + ps_view_ctxt->ps_mv_cur = ps_mvcd_ctxt->ps_cur_au->ps_au_mv_data->aps_mvs[u2_view_id]; + ps_view_ctxt->ps_mv_top = ps_view_ctxt->ps_mv_top_p[0]; + ps_view_ctxt->u1_mv_top_p = 0; + ps_view_ctxt->ps_mv_left = ps_mvcd_ctxt->ps_cur_au->ps_au_mv_data->aps_mvs[u2_view_id]; + ps_view_ctxt->ps_mv = ps_mvcd_ctxt->ps_cur_au->ps_au_mv_data->aps_mvs[u2_view_id]; + ps_view_ctxt->ps_mv_bank_cur = ps_mvcd_ctxt->ps_cur_au->ps_au_mv_data->aps_mvs[u2_view_id]; + ps_view_ctxt->pu1_col_zero_flag = + ps_mvcd_ctxt->ps_cur_au->ps_au_mv_data->apu1_mode_descriptors[u2_view_id]; + ps_view_ctxt->u2_mv_2mb[0] = 0; + ps_view_ctxt->u2_mv_2mb[1] = 0; + + ps_view_ctxt->u1_last_pic_not_decoded = 0; + ps_view_ctxt->u2_cur_slice_num_dec_thread = 0; + ps_view_ctxt->u2_cur_slice_num_bs = 0; + + ps_view_ctxt->u4_intra_pred_line_ofst = 0; + ps_view_ctxt->pu1_cur_y_intra_pred_line = ps_view_ctxt->pu1_y_intra_pred_line; + ps_view_ctxt->pu1_cur_u_intra_pred_line = ps_view_ctxt->pu1_u_intra_pred_line; + ps_view_ctxt->pu1_cur_v_intra_pred_line = ps_view_ctxt->pu1_v_intra_pred_line; + ps_view_ctxt->pu1_cur_y_intra_pred_line_base = ps_view_ctxt->pu1_y_intra_pred_line; + ps_view_ctxt->pu1_cur_u_intra_pred_line_base = ps_view_ctxt->pu1_u_intra_pred_line; + ps_view_ctxt->pu1_cur_v_intra_pred_line_base = ps_view_ctxt->pu1_v_intra_pred_line; + ps_view_ctxt->pu1_prev_y_intra_pred_line = + ps_view_ctxt->pu1_y_intra_pred_line + (ps_view_ctxt->u2_frm_wd_in_mbs * MB_SIZE); + ps_view_ctxt->pu1_prev_u_intra_pred_line = + ps_view_ctxt->pu1_u_intra_pred_line + + ps_view_ctxt->u2_frm_wd_in_mbs * BLK8x8SIZE * YUV420SP_FACTOR; + ps_view_ctxt->pu1_prev_v_intra_pred_line = + ps_view_ctxt->pu1_v_intra_pred_line + ps_view_ctxt->u2_frm_wd_in_mbs * BLK8x8SIZE; + + ps_view_ctxt->ps_deblk_mbn = ps_view_ctxt->ps_deblk_pic; + + ps_view_ctxt->pf_compute_bs = ih264d_compute_bs_non_mbaff; + ps_view_ctxt->u1_cur_mb_fld_dec_flag = ps_cur_slice->u1_field_pic_flag; + + if(0 == u2_view_order_id) + { + imvcd_assign_pic_num(ps_mvcd_ctxt->ps_dpb_mgr, ps_sps->u2_u4_max_pic_num_minus1 + 1, + ps_mvcd_ctxt->ps_cur_au->i4_frame_num, + ps_sps->u1_gaps_in_frame_num_value_allowed_flag); + + ps_view_ctxt->s_tran_addrecon.u2_mv_top_left_inc = (ps_view_ctxt->u1_recon_mb_grp << 2) - 1; + ps_view_ctxt->s_tran_addrecon.u2_mv_left_inc = (ps_view_ctxt->u1_recon_mb_grp - 1) << 4; + } + + if((ps_sps->u1_profile_idc == HIGH_PROFILE_IDC) || + (ps_sps->u1_profile_idc == MULTIVIEW_HIGH_PROFILE_IDC)) + { + if((ps_sps->i4_seq_scaling_matrix_present_flag) || + (ps_pps->i4_pic_scaling_matrix_present_flag)) + { + i4_error_code = ih264d_form_scaling_matrix_picture(ps_sps, ps_pps, ps_view_ctxt); + ps_view_ctxt->s_high_profile.u1_scaling_present = 1; + } + else + { + i4_error_code = ih264d_form_default_scaling_matrix(ps_view_ctxt); + } + + if(ps_pps->i4_transform_8x8_mode_flag) + { + ps_view_ctxt->s_high_profile.u1_transform8x8_present = 1; + } + } + else + { + i4_error_code = ih264d_form_default_scaling_matrix(ps_view_ctxt); + } + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ps_view_ctxt->s_high_profile.u1_direct_8x8_inference_flag = + ps_sps->u1_direct_8x8_inference_flag; + ps_view_ctxt->s_high_profile.s_cavlc_ctxt = ps_view_ctxt->s_cavlc_ctxt; + + ps_view_ctxt->i1_recon_in_thread3_flag = 1; + + ps_view_ctxt->ps_cur_pic = &ps_view_ctxt->s_cur_pic; + imvcd_convert_au_buf_to_view_buf(ps_mvcd_ctxt->ps_cur_au, &ps_view_ctxt->s_cur_pic, + u2_view_order_id, u2_view_id); + + ih264d_init_deblk_tfr_ctxt(ps_view_ctxt, &ps_view_ctxt->s_pad_mgr, + &ps_view_ctxt->s_tran_addrecon, ps_view_ctxt->u2_frm_wd_in_mbs, 0); + + ps_view_ctxt->ps_frame_buf_ip_recon = &ps_view_ctxt->s_tran_addrecon; + + if(ps_view_ctxt->u1_separate_parse) + { + ps_view_ctxt->s_tran_addrecon_parse = ps_view_ctxt->s_tran_addrecon; + + if((ps_view_ctxt->u4_num_cores >= 3) && ps_view_ctxt->i1_recon_in_thread3_flag) + { + ps_view_ctxt->s_tran_iprecon = ps_view_ctxt->s_tran_addrecon; + ps_view_ctxt->ps_frame_buf_ip_recon = &ps_view_ctxt->s_tran_iprecon; + } + } + + ps_view_ctxt->ps_cur_deblk_mb = ps_view_ctxt->ps_deblk_pic; + ps_view_ctxt->u4_cur_deblk_mb_num = 0; + + ps_view_ctxt->u4_deblk_mb_x = 0; + ps_view_ctxt->u4_deblk_mb_y = 0; + ps_view_ctxt->pu4_wt_ofsts = ps_view_ctxt->pu4_wts_ofsts_mat; + + ps_view_ctxt->u4_first_slice_in_pic = 0; + + return OK; +} + +static WORD32 imvcd_corrupted_slice_handler(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_mb_info_t *ps_cur_mb_info; + parse_pmbarams_t *ps_parse_mb_data; + deblk_mb_t *ps_cur_deblk_mb; + parse_part_params_t *ps_part_info; + + UWORD32 u4_num_mbs_next; + bool b_is_end_of_row; + bool b_is_slice_end; + bool b_tfr_n_mb; + bool b_decode_nmb; + UWORD8 u1_inter_mb_type; + UWORD8 u1_deblk_mb_type; + UWORD32 u4_num_mbsNby2; + UWORD16 i2_cur_mb_addr; + UWORD32 u4_mb_skip_run; + WORD32 i, j; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_slice_params_t *ps_slice = ps_view_ctxt->ps_cur_slice; + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + + UWORD32 u4_num_mbs = 0; + UWORD32 u4_mb_idx = ps_view_ctxt->u1_mb_idx; + UWORD32 u4_remaining_mbs = + (ps_view_ctxt->ps_cur_sps->u2_max_mb_addr + 1) - ps_view_ctxt->u2_total_mbs_coded; + + if(ps_view_ctxt->ps_dec_err_status->u1_err_flag & REJECT_CUR_PIC) + { + imvcd_free_ref_and_io_bufs(&ps_mvcd_ctxt->s_mvc_au_buf_mgr, + &ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr, + ps_mvcd_ctxt->ps_cur_au->i4_pic_buf_id); + + return OK; + } + + if((ISLICE == ps_slice->u1_slice_type) || (0 == ps_view_ctxt->u2_total_mbs_coded)) + { + yuv_buf_props_t *ps_view_buf = + &ps_mvcd_ctxt->ps_cur_au->as_view_buffers[ps_cur_nalu_mvc_ext->u2_view_id]; + + for(i = 0; i < NUM_SP_COMPONENTS; i++) + { + buffer_container_t *ps_component_buf = &ps_view_buf->as_component_bufs[i]; + + bool b_is_chroma = ((COMPONENT_TYPES_T) i) != Y; + UWORD16 u2_height = ps_view_buf->u2_height >> b_is_chroma; + UWORD16 u2_width = ps_view_buf->u2_width; + + for(j = 0; j < u2_height; j++) + { + UWORD8 *pu1_data = + ((UWORD8 *) ps_component_buf->pv_data) + j * ps_component_buf->i4_data_stride; + + memset(pu1_data, 128, u2_width * sizeof(pu1_data[0])); + } + } + + memset(ps_view_ctxt->apv_buf_id_pic_buf_map, 0, + sizeof(ps_view_ctxt->apv_buf_id_pic_buf_map)); + + ps_view_ctxt->apv_buf_id_pic_buf_map[ps_mvcd_ctxt->ps_cur_au->i4_pic_buf_id] = + &ps_view_ctxt->s_cur_pic; + ps_view_ctxt->ps_ref_pic_buf_lx[0] = &ps_view_ctxt->ps_cur_pic; + (ps_view_ctxt->ppv_map_ref_idx_to_poc + FRM_LIST_L0)[0] = + ps_view_ctxt->ps_cur_pic->pu1_buf1; + (ps_view_ctxt->ppv_map_ref_idx_to_poc + FRM_LIST_L1)[0] = NULL; + } + + ps_view_ctxt->ps_dpb_cmds->u1_long_term_reference_flag = 0; + + if(ps_view_ctxt->u2_total_mbs_coded > 0) + { + ps_view_ctxt->u2_total_mbs_coded -= + ps_view_ctxt->u2_total_mbs_coded % ps_view_ctxt->ps_cur_sps->u2_frm_wd_in_mbs; + u4_remaining_mbs = + (ps_view_ctxt->ps_cur_sps->u2_max_mb_addr + 1) - ps_view_ctxt->u2_total_mbs_coded; + + while(ps_view_ctxt->u4_dec_thread_created && + (ps_view_ctxt->cur_dec_mb_num < ps_view_ctxt->u2_total_mbs_coded)) + { + NOP(1 << 10); + } + + while(ps_view_ctxt->u4_bs_deblk_thread_created && + (ps_view_ctxt->cur_recon_mb_num < ps_view_ctxt->u2_total_mbs_coded)) + { + NOP(1 << 10); + } + + while(ps_view_ctxt->u4_bs_deblk_thread_created && + (ps_view_ctxt->u4_cur_deblk_mb_num < ps_view_ctxt->u2_total_mbs_coded)) + { + NOP(1 << 10); + } + + ps_view_ctxt->ps_nmb_info = ps_view_ctxt->ps_frm_mb_info + ps_view_ctxt->u2_total_mbs_coded; + ps_view_ctxt->ps_deblk_mbn = ps_view_ctxt->ps_cur_deblk_mb = + ps_view_ctxt->ps_deblk_pic + ps_view_ctxt->u2_total_mbs_coded; + } + + u4_num_mbs = ps_view_ctxt->u4_num_mbs_cur_nmb = 0; + + if(ps_view_ctxt->u1_separate_parse) + { + ps_cur_mb_info = ps_view_ctxt->ps_nmb_info; + } + else + { + ps_cur_mb_info = ps_view_ctxt->ps_nmb_info + ps_view_ctxt->u4_num_mbs_prev_nmb - 1; + } + + ps_view_ctxt->u2_mby = ps_cur_mb_info->u2_mby; + ps_view_ctxt->u2_mbx = ps_cur_mb_info->u2_mbx; + + ps_view_ctxt->u1_mb_ngbr_availablity = ps_cur_mb_info->u1_mb_ngbr_availablity; + + if(ps_view_ctxt->u2_total_mbs_coded >= (ps_view_ctxt->ps_cur_sps->u2_max_mb_addr + 1)) + { + ps_view_ctxt->u1_pic_decode_done = 1; + + return OK; + } + + /******************************************************/ + /* Initializations to new slice */ + /******************************************************/ + ps_view_ctxt->ps_parse_cur_slice->ppv_map_ref_idx_to_poc = + (volatile void **) ps_view_ctxt->pv_map_ref_idx_to_poc_buf; + ps_slice->i1_slice_alpha_c0_offset = 0; + ps_slice->i1_slice_beta_offset = 0; + ps_slice->u2_first_mb_in_slice = ps_view_ctxt->u2_total_mbs_coded; + ps_view_ctxt->ps_parse_cur_slice->u4_first_mb_in_slice = ps_view_ctxt->u2_total_mbs_coded; + ps_view_ctxt->ps_parse_cur_slice->u2_log2Y_crwd = ps_slice->u2_log2Y_crwd; + + if(ps_view_ctxt->u1_separate_parse) + { + ps_view_ctxt->ps_parse_cur_slice->pv_tu_coeff_data_start = + ps_view_ctxt->pv_parse_tu_coeff_data; + } + else + { + ps_view_ctxt->pv_proc_tu_coeff_data = ps_view_ctxt->pv_parse_tu_coeff_data; + } + + /******************************************************/ + /* Initializations specific to P slice */ + /******************************************************/ + u1_inter_mb_type = P_MB; + u1_deblk_mb_type = D_INTER_MB; + + ps_slice->u1_slice_type = P_SLICE; + ps_view_ctxt->ps_parse_cur_slice->slice_type = P_SLICE; + ps_view_ctxt->pf_mvpred_ref_tfr_nby2mb = ih264d_mv_pred_ref_tfr_nby2_pmb; + ps_view_ctxt->ps_part = ps_view_ctxt->ps_parse_part_params; + ps_view_ctxt->u2_mbx = + MOD(ps_view_ctxt->u2_total_mbs_coded - 1, ps_view_ctxt->u2_frm_wd_in_mbs); + ps_view_ctxt->u2_mby = + DIV(ps_view_ctxt->u2_total_mbs_coded - 1, ps_view_ctxt->u2_frm_wd_in_mbs); + + /******************************************************/ + /* Parsing / decoding the slice */ + /******************************************************/ + ps_view_ctxt->u1_qp = ps_slice->u1_slice_qp; + ih264d_update_qp(ps_view_ctxt, 0); + u4_mb_idx = ps_view_ctxt->u1_mb_idx; + ps_parse_mb_data = ps_view_ctxt->ps_parse_mb_data; + u4_num_mbs = u4_mb_idx; + + b_is_slice_end = false; + b_tfr_n_mb = false; + b_decode_nmb = false; + u4_num_mbsNby2 = 0; + i2_cur_mb_addr = ps_view_ctxt->u2_total_mbs_coded; + u4_mb_skip_run = u4_remaining_mbs; + + while(!b_is_slice_end) + { + if(i2_cur_mb_addr > ps_view_ctxt->ps_cur_sps->u2_max_mb_addr) + { + break; + } + + ps_cur_mb_info = ps_view_ctxt->ps_nmb_info + u4_num_mbs; + ps_view_ctxt->u4_num_mbs_cur_nmb = u4_num_mbs; + + ps_cur_mb_info->u1_Mux = 0; + ps_cur_mb_info->u1_end_of_slice = 0; + + ps_view_ctxt->u4_num_pmbair = u4_num_mbs; + ps_cur_deblk_mb = ps_view_ctxt->ps_deblk_mbn + u4_num_mbs; + + ps_parse_mb_data->u1_num_part = 1; + ps_parse_mb_data->u1_isI_mb = 0; + + /**************************************************************/ + /* Get the required information for decoding of MB */ + /**************************************************************/ + /* mb_x, mb_y, neighbor availablity, */ + ih264d_get_mb_info_cavlc_nonmbaff(ps_view_ctxt, i2_cur_mb_addr, ps_cur_mb_info, + u4_mb_skip_run); + + if(ps_view_ctxt->u4_app_disable_deblk_frm == 0) + { + ih264d_set_deblocking_parameters(ps_cur_deblk_mb, ps_slice, + ps_view_ctxt->u1_mb_ngbr_availablity, + ps_view_ctxt->u1_cur_mb_fld_dec_flag); + } + + ps_view_ctxt->i1_prev_mb_qp_delta = 0; + ps_view_ctxt->u1_sub_mb_num = 0; + ps_cur_mb_info->u1_mb_type = MB_SKIP; + ps_cur_mb_info->u1_mb_mc_mode = PRED_16x16; + ps_cur_mb_info->u1_cbp = 0; + + /* Storing Skip partition info */ + ps_part_info = ps_view_ctxt->ps_part; + ps_part_info->u1_is_direct = PART_DIRECT_16x16; + ps_part_info->u1_sub_mb_num = 0; + ps_view_ctxt->ps_part++; + + /* Update Nnzs */ + ih264d_update_nnz_for_skipmb(ps_view_ctxt, ps_cur_mb_info, CAVLC); + + ps_cur_mb_info->ps_curmb->u1_mb_type = u1_inter_mb_type; + ps_cur_deblk_mb->u1_mb_type |= u1_deblk_mb_type; + + u4_mb_skip_run--; + + ps_cur_deblk_mb->u1_mb_qp = ps_view_ctxt->u1_qp; + ps_cur_deblk_mb->u1_deblocking_mode = MB_DISABLE_FILTERING; + + i2_cur_mb_addr++; + u4_num_mbs++; + u4_num_mbsNby2++; + ps_parse_mb_data++; + + /****************************************************************/ + /* Check for End Of Row and other flags that determine when to */ + /* do DMA setup for N/2-Mb, Decode for N-Mb, and Transfer for */ + /* N-Mb */ + /****************************************************************/ + u4_num_mbs_next = ps_view_ctxt->ps_cur_sps->u2_frm_wd_in_mbs - 1 - ps_view_ctxt->u2_mbx; + b_is_end_of_row = (0 == u4_num_mbs_next); + b_is_slice_end = !u4_mb_skip_run; + ps_cur_mb_info->u1_end_of_slice = !u4_mb_skip_run; + b_tfr_n_mb = + (u4_num_mbs == ps_view_ctxt->u1_recon_mb_grp) || b_is_end_of_row || b_is_slice_end; + b_decode_nmb = b_tfr_n_mb || b_is_slice_end; + + if(b_decode_nmb) + { + ps_view_ctxt->pf_mvpred_ref_tfr_nby2mb(ps_view_ctxt, u4_mb_idx, u4_num_mbs); + + u4_num_mbsNby2 = 0; + ps_parse_mb_data = ps_view_ctxt->ps_parse_mb_data; + ps_view_ctxt->ps_part = ps_view_ctxt->ps_parse_part_params; + + if(ps_view_ctxt->u1_separate_parse) + { + ih264d_parse_tfr_nmb(ps_view_ctxt, u4_mb_idx, u4_num_mbs, u4_num_mbs_next, + b_tfr_n_mb, b_is_end_of_row); + + ps_view_ctxt->ps_nmb_info += u4_num_mbs; + } + else + { + ih264d_decode_recon_tfr_nmb(ps_view_ctxt, u4_mb_idx, u4_num_mbs, u4_num_mbs_next, + b_tfr_n_mb, b_is_end_of_row); + } + + ps_view_ctxt->u2_total_mbs_coded += u4_num_mbs; + + if(b_tfr_n_mb) + { + u4_num_mbs = 0; + } + + u4_mb_idx = u4_num_mbs; + ps_view_ctxt->u1_mb_idx = u4_num_mbs; + } + } + + ps_view_ctxt->u4_num_mbs_cur_nmb = 0; + ps_view_ctxt->i2_prev_slice_mbx = ps_view_ctxt->u2_mbx; + ps_view_ctxt->i2_prev_slice_mby = ps_view_ctxt->u2_mby; + + if(ps_view_ctxt->u2_total_mbs_coded >= (ps_view_ctxt->ps_cur_sps->u2_max_mb_addr + 1)) + { + ps_view_ctxt->u1_pic_decode_done = 1; + } + + return 0; +} + +static WORD32 imvcd_parse_pslice(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + UWORD8 u1_num_ref_idx_l0, u1_num_ref_idx_l1; + WORD32 i4_error_code; + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + dec_pic_params_t *ps_pps = ps_view_ctxt->ps_cur_pps; + dec_slice_params_t *ps_slice = ps_view_ctxt->ps_cur_slice; + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + ps_view_ctxt->s_default_mv_pred = imvcd_get_default_mv_pred(); + + i4_error_code = imvcd_set_ref_idx_override_flag(ps_view_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(ps_slice->u1_num_ref_idx_active_override_flag) + { + i4_error_code = imvcd_set_num_ref_idx_active(ps_view_ctxt, &u1_num_ref_idx_l0); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + else + { + u1_num_ref_idx_l0 = ps_view_ctxt->ps_cur_pps->u1_num_ref_idx_lx_active[0]; + } + + u1_num_ref_idx_l1 = 0; + + ps_slice->u1_num_ref_idx_lx_active[0] = u1_num_ref_idx_l0; + ps_slice->u1_num_ref_idx_lx_active[1] = u1_num_ref_idx_l1; + ps_view_ctxt->u1_num_ref_idx_lx_active_prev = ps_slice->u1_num_ref_idx_lx_active[0]; + + i4_error_code = + imvcd_init_ref_pic_list(ps_mvcd_ctxt->ps_dpb_mgr, ps_cur_nalu_mvc_ext, + ps_mvcd_ctxt->ps_cur_au, ps_mvcd_ctxt->u2_num_views_decoded); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_ref_pic_list_mod_data(ps_mvcd_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_dpb_reorder_ref_pic_list( + ps_mvcd_ctxt->ps_dpb_mgr, ps_cur_nalu_mvc_ext, ps_mvcd_ctxt->ps_cur_au, + imvcd_get_cur_ref_pic_list_mod_data(ps_mvcd_ctxt), ps_mvcd_ctxt->u2_num_views_decoded); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + ps_view_ctxt->ps_ref_pic_buf_lx[0] = imvcd_dpb_get_view_ref_pic_list( + ps_mvcd_ctxt->ps_dpb_mgr, ps_mvcd_ctxt->u2_num_views_decoded, + ps_cur_nalu_mvc_ext->u2_view_id, 0); + + for(i = 0; i < u1_num_ref_idx_l0; i++) + { + if(NULL == ps_view_ctxt->ps_ref_pic_buf_lx[0][i]->pu1_buf1) + { + return ERROR_FEATURE_UNAVAIL; + } + } + + imvcd_set_view_buf_id_to_buf_map(ps_view_ctxt); + + imvcd_init_ref_idx_to_ref_buf_map(ps_mvcd_ctxt); + + if(ps_pps->u1_wted_pred_flag) + { + i4_error_code = ih264d_parse_pred_weight_table(ps_slice, ps_bitstrm); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ih264d_form_pred_weight_matrix(ps_view_ctxt); + } + else + { + ps_view_ctxt->ps_cur_slice->u2_log2Y_crwd = 0; + } + + ps_view_ctxt->pu4_wt_ofsts = ps_view_ctxt->pu4_wts_ofsts_mat; + ps_view_ctxt->ps_parse_cur_slice->u2_log2Y_crwd = ps_view_ctxt->ps_cur_slice->u2_log2Y_crwd; + + if(ps_slice->u1_nal_ref_idc != 0) + { + if(!ps_view_ctxt->ps_dpb_cmds->u1_dpb_commands_read) + { + WORD32 i4_bit_offset = ih264d_read_mmco_commands(ps_view_ctxt); + + if(i4_bit_offset < 0) + { + return ERROR_DBP_MANAGER_T; + } + + ps_view_ctxt->u4_bitoffset = i4_bit_offset; + } + else + { + ps_bitstrm->u4_ofst += ps_view_ctxt->u4_bitoffset; + } + } + + if(ps_pps->u1_entropy_coding_mode == CABAC) + { + i4_error_code = imvcd_set_cabac_init_idc(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + i4_error_code = imvcd_set_slice_qp(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_slice_deblk_params(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ps_view_ctxt->u1_slice_header_done = 1; + + if(ps_pps->u1_entropy_coding_mode) + { + ps_view_ctxt->pf_parse_inter_slice = ih264d_parse_inter_slice_data_cabac; + ps_view_ctxt->pf_parse_inter_mb = ih264d_parse_pmb_cabac; + ps_view_ctxt->pf_get_mb_info = ih264d_get_mb_info_cabac_nonmbaff; + + ih264d_init_cabac_contexts(P_SLICE, ps_view_ctxt); + } + else + { + ps_view_ctxt->pf_parse_inter_slice = ih264d_parse_inter_slice_data_cavlc; + ps_view_ctxt->pf_parse_inter_mb = ih264d_parse_pmb_cavlc; + ps_view_ctxt->pf_get_mb_info = ih264d_get_mb_info_cavlc_nonmbaff; + } + + ps_view_ctxt->pf_mvpred_ref_tfr_nby2mb = ih264d_mv_pred_ref_tfr_nby2_pmb; + + ps_view_ctxt->u1_B = 0; + + i4_error_code = + ps_view_ctxt->pf_parse_inter_slice(ps_view_ctxt, ps_slice, ps_slice->u2_first_mb_in_slice); + + return i4_error_code; +} + +static WORD32 imvcd_parse_bslice(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + UWORD8 u1_num_ref_idx_l0, u1_num_ref_idx_l1; + WORD32 i4_error_code; + WORD32 i, j; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + nalu_mvc_ext_t *ps_cur_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + dec_pic_params_t *ps_pps = ps_view_ctxt->ps_cur_pps; + dec_slice_params_t *ps_slice = ps_view_ctxt->ps_cur_slice; + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + + ps_view_ctxt->s_default_mv_pred = imvcd_get_default_mv_pred(); + + i4_error_code = imvcd_set_ref_idx_override_flag(ps_view_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(ps_slice->u1_num_ref_idx_active_override_flag) + { + i4_error_code = imvcd_set_num_ref_idx_active(ps_view_ctxt, &u1_num_ref_idx_l0); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_num_ref_idx_active(ps_view_ctxt, &u1_num_ref_idx_l1); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + else + { + u1_num_ref_idx_l0 = ps_view_ctxt->ps_cur_pps->u1_num_ref_idx_lx_active[0]; + u1_num_ref_idx_l1 = ps_view_ctxt->ps_cur_pps->u1_num_ref_idx_lx_active[1]; + } + + if((0 == u1_num_ref_idx_l0) || (0 == u1_num_ref_idx_l1)) + { + return ERROR_FEATURE_UNAVAIL; + } + + ps_slice->u1_num_ref_idx_lx_active[0] = u1_num_ref_idx_l0; + ps_slice->u1_num_ref_idx_lx_active[1] = u1_num_ref_idx_l1; + ps_view_ctxt->u1_num_ref_idx_lx_active_prev = + ps_view_ctxt->ps_cur_slice->u1_num_ref_idx_lx_active[0]; + + i4_error_code = + imvcd_init_ref_pic_list(ps_mvcd_ctxt->ps_dpb_mgr, ps_cur_nalu_mvc_ext, + ps_mvcd_ctxt->ps_cur_au, ps_mvcd_ctxt->u2_num_views_decoded); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_ref_pic_list_mod_data(ps_mvcd_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_dpb_reorder_ref_pic_list( + ps_mvcd_ctxt->ps_dpb_mgr, ps_cur_nalu_mvc_ext, ps_mvcd_ctxt->ps_cur_au, + imvcd_get_cur_ref_pic_list_mod_data(ps_mvcd_ctxt), ps_mvcd_ctxt->u2_num_views_decoded); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + for(i = 0; i < 2; i++) + { + ps_view_ctxt->ps_ref_pic_buf_lx[i] = imvcd_dpb_get_view_ref_pic_list( + ps_mvcd_ctxt->ps_dpb_mgr, ps_mvcd_ctxt->u2_num_views_decoded, + ps_cur_nalu_mvc_ext->u2_view_id, i); + + for(j = 0; j < ps_slice->u1_num_ref_idx_lx_active[i]; j++) + { + if(NULL == ps_view_ctxt->ps_ref_pic_buf_lx[i][j]->pu1_buf1) + { + return ERROR_FEATURE_UNAVAIL; + } + } + } + + imvcd_set_view_buf_id_to_buf_map(ps_view_ctxt); + + imvcd_init_ref_idx_to_ref_buf_map(ps_mvcd_ctxt); + + if(ps_pps->u1_wted_bipred_idc == 1) + { + i4_error_code = ih264d_parse_pred_weight_table(ps_slice, ps_bitstrm); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ih264d_form_pred_weight_matrix(ps_view_ctxt); + + ps_view_ctxt->pu4_wt_ofsts = ps_view_ctxt->pu4_wts_ofsts_mat; + } + else if(ps_pps->u1_wted_bipred_idc == 2) + { + /* Implicit Weighted prediction */ + ps_slice->u2_log2Y_crwd = 0x0505; + ps_view_ctxt->pu4_wt_ofsts = ps_view_ctxt->pu4_wts_ofsts_mat; + + ih264d_get_implicit_weights(ps_view_ctxt); + } + else + { + ps_view_ctxt->ps_cur_slice->u2_log2Y_crwd = 0; + } + + ps_view_ctxt->ps_parse_cur_slice->u2_log2Y_crwd = ps_view_ctxt->ps_cur_slice->u2_log2Y_crwd; + + if(ps_slice->u1_nal_ref_idc != 0) + { + if(!ps_view_ctxt->ps_dpb_cmds->u1_dpb_commands_read) + { + WORD32 i4_bit_offset = ih264d_read_mmco_commands(ps_view_ctxt); + + if(i4_bit_offset < 0) + { + return ERROR_DBP_MANAGER_T; + } + + ps_view_ctxt->u4_bitoffset = i4_bit_offset; + } + else + { + ps_bitstrm->u4_ofst += ps_view_ctxt->u4_bitoffset; + } + } + + if(ps_pps->u1_entropy_coding_mode == CABAC) + { + i4_error_code = imvcd_set_cabac_init_idc(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + + i4_error_code = imvcd_set_slice_qp(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_slice_deblk_params(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ps_view_ctxt->u1_slice_header_done = 1; + + if(ps_pps->u1_entropy_coding_mode) + { + ps_view_ctxt->pf_parse_inter_slice = ih264d_parse_inter_slice_data_cabac; + ps_view_ctxt->pf_parse_inter_mb = ih264d_parse_bmb_cabac; + ps_view_ctxt->pf_get_mb_info = ih264d_get_mb_info_cabac_nonmbaff; + + ih264d_init_cabac_contexts(B_SLICE, ps_view_ctxt); + } + else + { + ps_view_ctxt->pf_parse_inter_slice = ih264d_parse_inter_slice_data_cavlc; + ps_view_ctxt->pf_parse_inter_mb = ih264d_parse_bmb_cavlc; + ps_view_ctxt->pf_get_mb_info = ih264d_get_mb_info_cavlc_nonmbaff; + } + + i4_error_code = ih264d_cal_col_pic(ps_view_ctxt); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + ps_view_ctxt->u1_B = 1; + + ps_view_ctxt->pf_mvpred_ref_tfr_nby2mb = ih264d_mv_pred_ref_tfr_nby2_bmb; + + i4_error_code = + ps_view_ctxt->pf_parse_inter_slice(ps_view_ctxt, ps_slice, ps_slice->u2_first_mb_in_slice); + + return i4_error_code; +} + +static WORD32 imvcd_parse_islice(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i4_error_code; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + i4_error_code = + ih264d_parse_islice(ps_view_ctxt, ps_view_ctxt->ps_cur_slice->u2_first_mb_in_slice); + + return i4_error_code; +} + +static WORD32 imvcd_finish_slice_decode(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_err_status_t *ps_err = ps_view_ctxt->ps_dec_err_status; + + UWORD16 u2_view_order_id = ps_mvcd_ctxt->u2_num_views_decoded; + UWORD16 u2_num_views = ps_mvcd_ctxt->u2_num_views; + + imvcd_dpb_reset_ivp_ctxt(ps_mvcd_ctxt->ps_dpb_mgr); + + /* End of Picture detection */ + if(ps_view_ctxt->u2_total_mbs_coded >= (ps_view_ctxt->ps_cur_sps->u2_max_mb_addr + 1)) + { + ps_view_ctxt->u1_pic_decode_done = 1; + } + else + { + imvcd_corrupted_slice_handler(ps_mvcd_ctxt); + + return ERROR_CORRUPTED_SLICE; + } + + if((ps_view_ctxt->u1_slice_header_done) && (u2_view_order_id == (u2_num_views - 1))) + { + ps_view_ctxt->u1_first_slice_in_stream = 0; + } + + if((ps_mvcd_ctxt->au1_nal_ref_idc[u2_view_order_id] != 0) && (0 == u2_view_order_id)) + { + if(!ps_view_ctxt->ps_dpb_cmds->u1_dpb_commands_read) + { + ps_view_ctxt->ps_dpb_cmds[0] = ps_view_ctxt->s_dpb_cmds_scratch; + } + } + + /* storing last Mb X and MbY of the slice */ + ps_view_ctxt->i2_prev_slice_mbx = ps_view_ctxt->u2_mbx; + ps_view_ctxt->i2_prev_slice_mby = ps_view_ctxt->u2_mby; + + if((ps_err->u1_err_flag & REJECT_PB_PICS) && (ps_err->u1_cur_pic_type == PIC_TYPE_I)) + { + ps_err->u1_err_flag = ACCEPT_ALL_PICS; + } + + /* Accounting for idiocy in 'ih264d_parse_sps' */ + if(u2_view_order_id > 0) + { + for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++) + { + if(ps_view_ctxt->ps_sps->u1_is_valid) + { + ps_view_ctxt->ps_cur_sps = ps_view_ctxt->ps_sps; + + break; + } + } + } + + return OK; +} + +WORD32 imvcd_parse_decode_slice(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_pic_params_t *ps_pps; + dec_seq_params_t *ps_sps; + dec_slice_params_t *ps_cur_slice; + + WORD32 i4_error_code; + UWORD8 u1_pps_id; + UWORD8 u1_pic_order_cnt_type; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + nalu_mvc_ext_t *ps_nalu_mvc_ext = imvcd_get_cur_nalu_mvc_ext(ps_mvcd_ctxt); + dec_bit_stream_t *ps_bitstrm = ps_view_ctxt->ps_bitstrm; + pocstruct_t s_tmp_poc = {0}; + dec_err_status_t *ps_err = ps_view_ctxt->ps_dec_err_status; + + WORD32 ai4_delta_poc[2] = {0}; + WORD32 i4_poc = 0; + UWORD32 u4_idr_pic_id = 0; + UWORD16 u2_view_id = ps_nalu_mvc_ext->u2_view_id; + UWORD16 u2_view_order_id = ps_mvcd_ctxt->u2_num_views_decoded; + bool b_is_idr_slice = imvcd_is_idr_au(ps_mvcd_ctxt); + UWORD16 u2_num_views = ps_mvcd_ctxt->u2_num_views; + UWORD8 u1_redundant_pic_cnt = 0; + const UWORD8 u1_field_pic_flag = 0; + const UWORD8 u1_bottom_field_flag = 0; + + ps_view_ctxt->ps_cur_slice = ps_cur_slice = &ps_mvcd_ctxt->as_slices[u2_view_id]; + ps_view_ctxt->ps_dpb_cmds->u1_dpb_commands_read_slc = 0; + + ps_cur_slice->u1_nal_unit_type = ps_mvcd_ctxt->ae_nalu_id[u2_view_order_id]; + ps_cur_slice->u1_nal_ref_idc = ps_mvcd_ctxt->au1_nal_ref_idc[u2_view_order_id]; + + i4_error_code = imvcd_set_first_mb_in_slice(ps_view_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_slice_type(ps_view_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + i4_error_code = imvcd_set_cur_pps(ps_view_ctxt, &u1_pps_id); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + ps_pps = ps_view_ctxt->ps_cur_pps; + ps_sps = ps_view_ctxt->ps_cur_sps; + + i4_error_code = imvcd_set_frame_num(ps_view_ctxt, ps_sps->u1_bits_in_frm_num); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(!ps_view_ctxt->u1_first_slice_in_stream && ps_view_ctxt->u4_first_slice_in_pic) + { + ps_view_ctxt->u2_mbx = 0xffff; + ps_view_ctxt->u2_mby = 0; + ps_view_ctxt->u2_total_mbs_coded = 0; + + if(0 == u2_view_order_id) + { + if(b_is_idr_slice || ps_cur_slice->u1_mmco_equalto5) + { + ps_view_ctxt->u2_prev_ref_frame_num = 0; + } + + if(ps_view_ctxt->ps_cur_sps->u1_gaps_in_frame_num_value_allowed_flag) + { + i4_error_code = imvcd_decode_gaps_in_frame_num(ps_mvcd_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + + if(!b_is_idr_slice && ps_cur_slice->u1_nal_ref_idc) + { + ps_view_ctxt->u2_prev_ref_frame_num = ps_cur_slice->u2_frame_num; + } + + imvcd_pocstruct_init(ps_view_ctxt); + } + } + + if(b_is_idr_slice) + { + i4_error_code = imvcd_set_idr_pic_id(ps_view_ctxt, &u4_idr_pic_id); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + /* 'ih264d_read_mmco_commands' asssumes AVC semantics */ + ps_view_ctxt->u1_nal_unit_type = SLICE_IDR; + } + else + { + ps_view_ctxt->u1_nal_unit_type = SLICE_NON_IDR; + } + + u1_pic_order_cnt_type = ps_sps->u1_pic_order_cnt_type; + + if(0 == u1_pic_order_cnt_type) + { + i4_error_code = imvcd_set_poc_lsb(ps_view_ctxt, &s_tmp_poc.i4_pic_order_cnt_lsb, + ps_sps->i4_max_pic_order_cntLsb, + ps_sps->u1_log2_max_pic_order_cnt_lsb_minus); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(ps_pps->u1_pic_order_present_flag) + { + i4_error_code = + imvcd_set_delta_poc(ps_view_ctxt, &s_tmp_poc.i4_delta_pic_order_cnt_bottom); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + } + + if((1 == u1_pic_order_cnt_type) && !ps_sps->u1_delta_pic_order_always_zero_flag) + { + i4_error_code = imvcd_set_delta_poc(ps_view_ctxt, &s_tmp_poc.i4_delta_pic_order_cnt[0]); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(ps_pps->u1_pic_order_present_flag) + { + i4_error_code = imvcd_set_delta_poc(ps_view_ctxt, &s_tmp_poc.i4_delta_pic_order_cnt[1]); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + } + + if(ps_pps->u1_redundant_pic_cnt_present_flag) + { + i4_error_code = imvcd_set_redundant_pic_cnt(ps_view_ctxt, &u1_redundant_pic_cnt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + } + + ps_view_ctxt->ps_dec_err_status->u1_err_flag &= MASK_REJECT_CUR_PIC; + + ps_view_ctxt->u1_slice_header_done = 0; + + if(ps_view_ctxt->u4_first_slice_in_pic) + { + i4_error_code = ih264d_decode_pic_order_cnt( + b_is_idr_slice, ps_cur_slice->u2_frame_num, &ps_view_ctxt->s_prev_pic_poc, &s_tmp_poc, + ps_cur_slice, ps_pps, ps_mvcd_ctxt->au1_nal_ref_idc[u2_view_order_id], + u1_bottom_field_flag, u1_field_pic_flag, &i4_poc); + + if(i4_error_code != OK) + { + return i4_error_code; + } + + /* Display seq no calculations */ + if(i4_poc >= ps_view_ctxt->i4_max_poc) + { + ps_view_ctxt->i4_max_poc = i4_poc; + } + + /* IDR Picture or POC wrap around */ + if(i4_poc == 0) + { + WORD64 i8_temp = ps_view_ctxt->i4_prev_max_display_seq + ps_view_ctxt->i4_max_poc + + ps_view_ctxt->u1_max_dec_frame_buffering + 1; + + /*If i4_prev_max_display_seq overflows integer range, reset it */ + ps_view_ctxt->i4_prev_max_display_seq = + IS_OUT_OF_RANGE_S32(i8_temp) ? 0 : (WORD32) i8_temp; + ps_view_ctxt->i4_max_poc = 0; + } + } + + if((0 == i4_poc) && (ps_mvcd_ctxt->ae_nalu_id[u2_view_order_id] == SLICE_IDR) && + (ps_cur_slice->u1_slice_type != ISLICE)) + { + return ERROR_INV_SLICE_HDR_T; + } + + /*--------------------------------------------------------------------*/ + /* Copy the values read from the bitstream to the slice header and then*/ + /* If the slice is first slice in picture, then do Start of Picture */ + /* processing. */ + /*--------------------------------------------------------------------*/ + ps_cur_slice->i4_delta_pic_order_cnt[0] = ai4_delta_poc[0]; + ps_cur_slice->i4_delta_pic_order_cnt[1] = ai4_delta_poc[1]; + ps_cur_slice->u4_idr_pic_id = u4_idr_pic_id; + ps_cur_slice->u1_field_pic_flag = u1_field_pic_flag; + ps_cur_slice->u1_bottom_field_flag = u1_bottom_field_flag; + ps_cur_slice->i4_pic_order_cnt_lsb = s_tmp_poc.i4_pic_order_cnt_lsb; + ps_cur_slice->u1_redundant_pic_cnt = u1_redundant_pic_cnt; + ps_cur_slice->u1_pic_order_cnt_type = u1_pic_order_cnt_type; + ps_cur_slice->i4_poc = i4_poc; + + ps_cur_slice->u1_direct_8x8_inference_flag = ps_sps->u1_direct_8x8_inference_flag; + + if(IV_SUCCESS != imvcd_view_error_checks(ps_mvcd_ctxt)) + { + return ERROR_INV_SLICE_HDR_T; + } + + if(ps_cur_slice->u1_slice_type == B_SLICE) + { + i4_error_code = imvcd_set_direct_spatial_mv_pred_flag(ps_view_ctxt); + + if(OK != i4_error_code) + { + return i4_error_code; + } + + if(ps_cur_slice->u1_direct_spatial_mv_pred_flag) + { + ps_cur_slice->pf_decodeDirect = ih264d_decode_spatial_direct; + } + else + { + ps_cur_slice->pf_decodeDirect = ih264d_decode_temporal_direct; + } + + ps_view_ctxt->pf_mvpred = ih264d_mvpred_nonmbaffB; + } + else + { + ps_view_ctxt->pf_mvpred = ih264d_mvpred_nonmbaff; + } + + if(ps_view_ctxt->u4_first_slice_in_pic) + { + if(0 == ps_cur_slice->u2_first_mb_in_slice) + { + i4_error_code = imvcd_pic_init(ps_mvcd_ctxt, &s_tmp_poc, i4_poc, b_is_idr_slice); + + if(i4_error_code != OK) + { + return i4_error_code; + } + } + else + { + return ERROR_INV_SLICE_HDR_T; + } + + ps_view_ctxt->u4_output_present = 0; + + if(u2_view_order_id == (u2_num_views - 1)) + { + if(IV_SUCCESS == imvcd_get_next_display_au_buf(ps_mvcd_ctxt)) + { + ps_view_ctxt->u4_output_present = 1; + } + } + + if(ps_view_ctxt->u1_separate_parse == 1) + { + if(!ps_view_ctxt->u4_dec_thread_created) + { + ithread_create(ps_view_ctxt->pv_dec_thread_handle, NULL, + ih264d_decode_picture_thread, ps_view_ctxt); + + ps_view_ctxt->u4_dec_thread_created = 1; + } + + if((3 == ps_view_ctxt->u4_num_cores) && + (!ps_view_ctxt->u4_app_disable_deblk_frm || + ps_view_ctxt->i1_recon_in_thread3_flag) && + !ps_view_ctxt->u4_bs_deblk_thread_created) + { + ps_view_ctxt->u4_start_recon_deblk = 0; + + ithread_create(ps_view_ctxt->pv_bs_deblk_thread_handle, NULL, + ih264d_recon_deblk_thread, ps_view_ctxt); + + ps_view_ctxt->u4_bs_deblk_thread_created = 1; + } + } + } + + if((ps_cur_slice->u1_slice_type != B_SLICE) && + (ps_view_ctxt->ps_cur_pps->u1_wted_pred_flag == 0)) + { + ps_view_ctxt->p_form_mb_part_info = ih264d_form_mb_part_info_bp; + ps_view_ctxt->p_motion_compensate = ih264d_motion_compensate_bp; + } + else + { + ps_view_ctxt->p_form_mb_part_info = ih264d_form_mb_part_info_mp; + ps_view_ctxt->p_motion_compensate = ih264d_motion_compensate_mp; + } + + if(ps_err->u4_frm_sei_sync == ps_cur_slice->u2_frame_num) + { + ps_err->u1_err_flag = ACCEPT_ALL_PICS; + ps_err->u4_frm_sei_sync = SYNC_FRM_DEFAULT; + } + + ps_err->u4_cur_frm = ps_cur_slice->u2_frame_num; + + ps_view_ctxt->i4_submb_ofst = -SUB_BLK_SIZE; + + ps_view_ctxt->u2_cur_mb_addr = 0; + ps_view_ctxt->ps_deblk_mbn = ps_view_ctxt->ps_deblk_pic; + ps_view_ctxt->ps_mv_cur = ps_mvcd_ctxt->ps_cur_au->ps_au_mv_data->aps_mvs[u2_view_id]; + + ps_view_ctxt->s_tran_addrecon.pu1_dest_y = + ps_mvcd_ctxt->ps_cur_au->as_view_buffers[u2_view_id].as_component_bufs[Y].pv_data; + ps_view_ctxt->s_tran_addrecon.pu1_dest_u = + ps_mvcd_ctxt->ps_cur_au->as_view_buffers[u2_view_id].as_component_bufs[UV].pv_data; + ps_view_ctxt->s_tran_addrecon.pu1_dest_v = NULL; + + ps_view_ctxt->s_tran_addrecon.pu1_mb_y = + ps_mvcd_ctxt->ps_cur_au->as_view_buffers[u2_view_id].as_component_bufs[Y].pv_data; + ps_view_ctxt->s_tran_addrecon.pu1_mb_u = + ps_mvcd_ctxt->ps_cur_au->as_view_buffers[u2_view_id].as_component_bufs[UV].pv_data; + ps_view_ctxt->s_tran_addrecon.pu1_mb_v = NULL; + + ps_view_ctxt->ps_part = ps_view_ctxt->ps_parse_part_params; + + ps_view_ctxt->u2_mbx = (MOD(ps_cur_slice->u2_first_mb_in_slice - 1, ps_sps->u2_frm_wd_in_mbs)); + ps_view_ctxt->u2_mby = (DIV(ps_cur_slice->u2_first_mb_in_slice - 1, ps_sps->u2_frm_wd_in_mbs)); + ps_view_ctxt->i2_prev_slice_mbx = ps_view_ctxt->u2_mbx; + ps_view_ctxt->i2_prev_slice_mby = ps_view_ctxt->u2_mby; + + /* RBSP stop bit is used for CABAC decoding*/ + ps_bitstrm->u4_max_ofst += ps_view_ctxt->ps_cur_pps->u1_entropy_coding_mode; + + ps_view_ctxt->u1_B = (ps_cur_slice->u1_slice_type == B_SLICE); + ps_view_ctxt->u4_next_mb_skip = 0; + + ps_view_ctxt->ps_parse_cur_slice->u4_first_mb_in_slice = ps_cur_slice->u2_first_mb_in_slice; + ps_view_ctxt->ps_parse_cur_slice->slice_type = ps_cur_slice->u1_slice_type; + + ps_view_ctxt->u4_start_recon_deblk = 1; + + ps_view_ctxt->ps_parse_cur_slice->ppv_map_ref_idx_to_poc = + ps_view_ctxt->pv_map_ref_idx_to_poc_buf; + + if(ps_view_ctxt->u1_separate_parse) + { + ps_view_ctxt->ps_parse_cur_slice->pv_tu_coeff_data_start = + ps_view_ctxt->pv_parse_tu_coeff_data; + } + else + { + ps_view_ctxt->pv_proc_tu_coeff_data = ps_view_ctxt->pv_parse_tu_coeff_data; + } + + if(0 == u2_view_order_id) + { + i4_error_code = imvcd_dpb_st_lt_deduplicator(ps_mvcd_ctxt->ps_dpb_mgr); + + if(i4_error_code < 0) + { + i4_error_code = ERROR_DBP_MANAGER_T; + } + } + + if(ps_cur_slice->u1_slice_type == I_SLICE) + { + ps_mvcd_ctxt->ps_cur_au->au4_pack_slc_typ[u2_view_order_id] |= I_SLC_BIT; + + i4_error_code = imvcd_parse_islice(ps_mvcd_ctxt); + + ps_view_ctxt->u1_pr_sl_type = ps_cur_slice->u1_slice_type; + + if(ps_view_ctxt->i4_pic_type != B_SLICE && ps_view_ctxt->i4_pic_type != P_SLICE) + { + ps_view_ctxt->i4_pic_type = I_SLICE; + } + } + else if(ps_cur_slice->u1_slice_type == P_SLICE) + { + ps_mvcd_ctxt->ps_cur_au->au4_pack_slc_typ[u2_view_order_id] |= P_SLC_BIT; + + i4_error_code = imvcd_parse_pslice(ps_mvcd_ctxt); + + ps_view_ctxt->u1_pr_sl_type = ps_cur_slice->u1_slice_type; + + if(ps_view_ctxt->i4_pic_type != B_SLICE) + { + ps_view_ctxt->i4_pic_type = P_SLICE; + } + } + else if(ps_cur_slice->u1_slice_type == B_SLICE) + { + ps_mvcd_ctxt->ps_cur_au->au4_pack_slc_typ[u2_view_order_id] |= B_SLC_BIT; + + i4_error_code = imvcd_parse_bslice(ps_mvcd_ctxt); + + ps_view_ctxt->u1_pr_sl_type = ps_cur_slice->u1_slice_type; + + ps_view_ctxt->i4_pic_type = B_SLICE; + } + else + { + i4_error_code = ERROR_INV_SLC_TYPE_T; + } + + i4_error_code = imvcd_finish_slice_decode(ps_mvcd_ctxt); + + return i4_error_code; +} diff --git a/decoder/mvc/imvcd_slice_functions.h b/decoder/mvc/imvcd_slice_functions.h new file mode 100644 index 0000000..62f85bf --- /dev/null +++ b/decoder/mvc/imvcd_slice_functions.h @@ -0,0 +1,36 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_slice_functions.h */ +/* */ +/* Description : Functions for MVC Slice parsing, etc. */ +/* */ +/*****************************************************************************/ + +#ifndef _IMVCD_SLICE_FUNCTIONS_H_ +#define _IMVCD_SLICE_FUNCTIONS_H_ + +#include "ih264_typedefs.h" +#include "imvcd_structs.h" + +extern WORD32 imvcd_parse_decode_slice(mvc_dec_ctxt_t *ps_mvcd_ctxt); +#endif diff --git a/decoder/mvc/imvcd_structs.h b/decoder/mvc/imvcd_structs.h new file mode 100644 index 0000000..7af1877 --- /dev/null +++ b/decoder/mvc/imvcd_structs.h @@ -0,0 +1,234 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ +#ifndef _IMVCD_STRUCTS_H_ +#define _IMVCD_STRUCTS_H_ + +#include + +#include "ih264_typedefs.h" +#include "imvcd.h" +#include "ih264_error.h" +#include "ih264_buf_mgr.h" +#include "ih264_disp_mgr.h" +#include "ih264d_sei.h" +#include "ih264d_structs.h" +#include "imvc_defs.h" +#include "imvc_structs.h" +#include "imvcd_defs.h" + +/* structs */ +typedef struct mvc_au_mv_pred_t +{ + mv_pred_t *aps_mvs[MAX_NUM_VIEWS]; + + /* colZeroFlag | // 0th bit + field_flag | // 1st bit + XX | // 2:3 bit don't cares + subMbMode | // 4:5 bit + MbMode | // 6:7 bit */ + UWORD8 *apu1_mode_descriptors[MAX_NUM_VIEWS]; + +} mvc_au_mv_pred_t; + +typedef struct ivp_data_t +{ + bool b_is_ivp_ref; + + /* Due to the structuring of dpb_mgr_t, */ + /* mvc_pic_buffer_t used for referencing ought to contain */ + /* all data in indices corresponding to view_id doing the referencing. */ + /* This struct, and this variable in particular, is used for identifying */ + /* the reference view's view_id */ + + UWORD16 u2_ref_view_id; +} ivp_data_t; + +typedef struct mvc_au_buffer_t +{ + /** pic_buffer for all views */ + yuv_buf_props_t as_view_buffers[MAX_NUM_VIEWS]; + + /** display offsets for all views */ + offsets_t as_disp_offsets[MAX_NUM_VIEWS]; + + ivp_data_t s_ivp_data; + + /** SEI data */ + sei s_sei_pic; + + /** AU MV Data */ + mvc_au_mv_pred_t *ps_au_mv_data; + + /* It will contain information about types of slices */ + UWORD32 au4_pack_slc_typ[MAX_NUM_VIEWS]; + + /** Width of the display luma frame in pixels */ + UWORD16 u2_disp_width; + + /** Height of the display luma frame in pixels */ + UWORD16 u2_disp_height; + + /** Time at which frame has to be displayed */ + UWORD32 u4_time_stamp; + + /** (1: short 0: long) term ref pic */ + bool b_is_short_term_ref; + + /** frame / field / complementary field pair */ + UWORD8 u1_pic_type; + + /** Idx into the picBufAPI array */ + WORD32 i4_pic_buf_id; + + WORD32 i4_mv_buf_id; + + WORD32 i4_poc; + + WORD32 i4_frame_num; + + /* Derived based on '8.2.4.1' */ + WORD32 i4_pic_num; + + /** minPOC */ + WORD32 i4_avg_poc; + + /*Same as u1_pic_type..u1_pic_type gets overwritten whereas this doesnot get + overwritten + ...stores the pictype of frame/complementary field pair/ mbaff */ + UWORD8 u1_picturetype; + + UWORD8 u1_long_term_frm_idx; + + UWORD8 u1_long_term_pic_num; + + /* Refer to SEI table D-1 */ + UWORD8 u1_pic_struct; + +} mvc_au_buffer_t; + +typedef struct mvc_au_buf_mgr_t +{ + void *pv_mem; + + buf_mgr_t *ps_buf_mgr_ctxt; + + void *pv_au_buf_base; + + mvc_au_buffer_t *aps_buf_id_to_au_buf_map[MAX_DISP_BUFS_NEW]; + + UWORD8 au1_au_buf_id_to_mv_buf_id_map[MAX_DISP_BUFS_NEW]; + + UWORD8 au1_au_buf_ref_flag[MAX_DISP_BUFS_NEW]; + +} mvc_au_buf_mgr_t; + +typedef struct mvc_au_mv_pred_buf_mgr_t +{ + void *pv_mem; + + buf_mgr_t *ps_buf_mgr_ctxt; + + void *pv_au_mv_pred_buf_base; + + mvc_au_mv_pred_t *aps_buf_id_to_mv_pred_buf_map[MAX_DISP_BUFS_NEW]; + +} mvc_au_mv_pred_buf_mgr_t; + +typedef struct subset_sps_t +{ + dec_seq_params_t s_sps_data; + + sps_mvc_ext_t s_sps_mvc_ext; + + mvc_vui_ext_t s_mvc_vui_ext; + + offsets_t s_disp_offsets; + + UWORD8 u1_mvc_vui_parameters_present_flag; + +} subset_sps_t; + +typedef struct ref_pic_list_mod_data_t +{ + UWORD8 au1_num_active_refs[2]; + + UWORD8 au1_ref_pic_list_modification_flag_lx[2]; + + UWORD8 au1_modification_of_pic_nums_idc[2][MVC_MAX_REF_PICS + 1]; + + WORD32 ai4_abs_diff_pic_num_minus1[2][MVC_MAX_REF_PICS + 1]; + + WORD32 ai4_long_term_pic_num[2][MVC_MAX_REF_PICS + 1]; + + WORD32 ai4_abs_diff_view_idx_minus1[2][MVC_MAX_REF_PICS + 1]; +} ref_pic_list_mod_data_t; + +typedef struct mvc_dec_ctxt_t +{ + dec_struct_t s_view_dec_ctxt; + + iv_mvc_yuv_buf_t s_out_buffer; + + /* Resolves circular dependency with mvc_dpb_manager_t */ + void *ps_dpb_mgr; + + subset_sps_t as_subset_sps[MAX_NUM_SEQ_PARAMS]; + + /* Indexed via viewOrderID */ + nalu_mvc_ext_t as_nalu_mvc_ext[MAX_NUM_VIEWS]; + + /* Indexed via viewOrderID */ + dec_slice_params_t as_slices[MAX_NUM_VIEWS]; + + ref_pic_list_mod_data_t as_ref_pic_list_mod_data[MAX_NUM_VIEWS]; + + subset_sps_t *aps_pps_id_to_subset_sps_map[MAX_NUM_PIC_PARAMS]; + + disp_mgr_t s_mvc_disp_buf_mgr; + + mvc_au_buf_mgr_t s_mvc_au_buf_mgr; + + mvc_au_mv_pred_buf_mgr_t s_mvc_au_mv_pred_buf_mgr; + + mvc_au_buffer_t *ps_cur_au; + + AVC_EXT_NALU_ID_T ae_nalu_id[MAX_NUM_VIEWS]; + + UWORD8 au1_nal_ref_idc[MAX_NUM_VIEWS]; + + UWORD32 u4_num_aus_decoded; + + UWORD16 u2_num_views; + + UWORD16 u2_num_views_decoded; + + UWORD8 u1_num_sps; + + UWORD8 u1_num_subset_sps; + + UWORD8 u1_num_pps; + + bool b_header_only_decode; + + bool b_flush_enabled; + +} mvc_dec_ctxt_t; + +#endif diff --git a/decoder/mvc/imvcd_utils.c b/decoder/mvc/imvcd_utils.c new file mode 100644 index 0000000..d92c50f --- /dev/null +++ b/decoder/mvc/imvcd_utils.c @@ -0,0 +1,1139 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_utils.c */ +/* */ +/* Description : MVCD Utility functions used by 'imvcd_api.c' */ +/* */ +/*****************************************************************************/ +#include + +#include "ih264_typedefs.h" +#include "iv.h" +#include "ih264_debug.h" +#include "ih264_disp_mgr.h" +#include "ih264_macros.h" +#include "ih264d_error_handler.h" +#include "ih264d_format_conv.h" +#include "ih264d_utils.h" +#include "imvcd_structs.h" +#include "imvcd_utils.h" + +void imvcd_free_ref_bufs(mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr, + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr, WORD32 i4_pic_buf_id) +{ + ih264_buf_mgr_release(ps_mvc_au_buf_mgr->ps_buf_mgr_ctxt, i4_pic_buf_id, BUF_MGR_REF); + + ih264_buf_mgr_release(ps_mvc_au_mv_pred_buf_mgr->ps_buf_mgr_ctxt, + ps_mvc_au_buf_mgr->au1_au_buf_id_to_mv_buf_id_map[i4_pic_buf_id], + BUF_MGR_REF); +} + +void imvcd_release_all_ref_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt, WORD32 i4_num_bufs) +{ + WORD32 i; + + for(i = 0; i < i4_num_bufs; i++) + { + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, i, BUF_MGR_REF); + + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, + ps_mvcd_ctxt->s_mvc_au_buf_mgr.au1_au_buf_id_to_mv_buf_id_map[i], + BUF_MGR_REF); + } +} + +void imvcd_free_ref_and_io_bufs(mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr, + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr, + WORD32 i4_pic_buf_id) +{ + ih264_buf_mgr_release(ps_mvc_au_buf_mgr->ps_buf_mgr_ctxt, i4_pic_buf_id, + BUF_MGR_REF | BUF_MGR_IO); + + ih264_buf_mgr_release(ps_mvc_au_mv_pred_buf_mgr->ps_buf_mgr_ctxt, + ps_mvc_au_buf_mgr->au1_au_buf_id_to_mv_buf_id_map[i4_pic_buf_id], + BUF_MGR_REF | BUF_MGR_IO); +} + +void imvcd_release_all_ref_and_io_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt, WORD32 i4_num_bufs) +{ + WORD32 i; + + for(i = 0; i < i4_num_bufs; i++) + { + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, i, + BUF_MGR_REF | BUF_MGR_IO); + + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, + ps_mvcd_ctxt->s_mvc_au_buf_mgr.au1_au_buf_id_to_mv_buf_id_map[i], + BUF_MGR_REF | BUF_MGR_IO); + } +} + +bool is_header_decoded(WORD32 i4_header_decoded, AVC_EXT_NALU_ID_T e_nalu_id) +{ + /* Accounting for idiocy in 'ih264d_parse_nal_unit' */ + e_nalu_id = (SPS == e_nalu_id) ? UNSPEC_0 : ((PPS == e_nalu_id) ? SLICE_NON_IDR : e_nalu_id); + return !!(i4_header_decoded & (1 << e_nalu_id)); +} + +bool is_mvc_nalu(AVC_EXT_NALU_ID_T e_nalu_id) +{ + switch(e_nalu_id) + { + case SLICE_NON_IDR: + case SLICE_DPA: + case SLICE_DPB: + case SLICE_DPC: + case SLICE_IDR: + case PREFIX_NAL: + case SUBSET_SPS: + case CODED_SLICE_EXTENSION: + { + return true; + } + default: + { + return false; + } + } +} + +bool is_slice_nalu_type(AVC_EXT_NALU_ID_T e_nalu_id) +{ + switch(e_nalu_id) + { + case SLICE_NON_IDR: + case SLICE_DPA: + case SLICE_DPB: + case SLICE_DPC: + case SLICE_IDR: + case CODED_SLICE_EXTENSION: + case PREFIX_NAL: + { + return true; + } + default: + { + return false; + } + } +} + +nalu_mvc_ext_t *imvcd_get_cur_nalu_mvc_ext(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + return &ps_mvcd_ctxt->as_nalu_mvc_ext[ps_mvcd_ctxt->u2_num_views_decoded]; +} + +nalu_mvc_ext_t *imvcd_get_nalu_mvc_ext(nalu_mvc_ext_t *ps_nalu_mvc_exts, + UWORD16 u2_num_views_decoded, UWORD16 u2_view_id) +{ + WORD32 i; + + for(i = 0; i < u2_num_views_decoded; i++) + { + if(ps_nalu_mvc_exts[i].u2_view_id == u2_view_id) + { + return &ps_nalu_mvc_exts[i]; + } + } + + return NULL; +} + +ref_pic_list_mod_data_t *imvcd_get_cur_ref_pic_list_mod_data(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + return &ps_mvcd_ctxt->as_ref_pic_list_mod_data[ps_mvcd_ctxt->u2_num_views_decoded]; +} + +subset_sps_t *imvcd_get_valid_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + if(0 != ps_mvcd_ctxt->u2_num_views_decoded) + { + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + return ps_mvcd_ctxt + ->aps_pps_id_to_subset_sps_map[ps_view_ctxt->ps_cur_pps->u1_pic_parameter_set_id]; + } + else + { + WORD32 i; + + for(i = 0; i < MAX_NUM_SEQ_PARAMS; i++) + { + if(ps_mvcd_ctxt->as_subset_sps[i].s_sps_data.u1_is_valid) + { + return &ps_mvcd_ctxt->as_subset_sps[i]; + } + } + + return NULL; + } +} + +void imvcd_modulate_max_disp_seq(dec_struct_t *ps_view_ctxt) +{ + WORD64 i8_temp; + + i8_temp = ps_view_ctxt->i4_prev_max_display_seq + ps_view_ctxt->i4_max_poc + + ps_view_ctxt->u1_max_dec_frame_buffering + 1; + + ps_view_ctxt->i4_prev_max_display_seq = IS_OUT_OF_RANGE_S32(i8_temp) ? 0 : ((WORD32) i8_temp); + ps_view_ctxt->i4_max_poc = 0; +} + +mv_pred_t imvcd_get_default_mv_pred(void) +{ + mv_pred_t s_mv_pred = {.i2_mv = {0}, + .i1_ref_frame = {OUT_OF_RANGE_REF, OUT_OF_RANGE_REF}, + .u1_col_ref_pic_idx = UINT8_MAX, + .u1_pic_type = UINT8_MAX}; + + return s_mv_pred; +} + +UWORD32 imvcd_get_max_num_ivp_refs(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + WORD32 i; + + subset_sps_t *ps_subset_sps = imvcd_get_valid_subset_sps(ps_mvcd_ctxt); + + UWORD32 u4_max_ivp_refs = 0; + + if(!ps_subset_sps) + { + return u4_max_ivp_refs; + } + + for(i = 0; i < ps_subset_sps->s_sps_mvc_ext.u2_num_views; i++) + { + u4_max_ivp_refs = MAX( + u4_max_ivp_refs, ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[0][i].u1_num_refs + + ps_subset_sps->s_sps_mvc_ext.as_anchor_ref_data[1][i].u1_num_refs); + u4_max_ivp_refs = + MAX(u4_max_ivp_refs, + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[0][i].u1_num_refs + + ps_subset_sps->s_sps_mvc_ext.as_non_anchor_ref_data[1][i].u1_num_refs); + } + + return u4_max_ivp_refs; +} + +bool imvcd_is_idr_au(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + return (ps_mvcd_ctxt->u2_num_views_decoded > 1) + ? !ps_mvcd_ctxt->as_nalu_mvc_ext->u1_non_idr_flag + : (ps_mvcd_ctxt->ae_nalu_id[0] == SLICE_IDR); +} + +coordinates_t imvcd_get_buf_pad_dims(bool b_is_chroma) +{ + coordinates_t s_dims; + + /* Vert pad is '4 * PAD_LEN_UV_V' to account for field Pics */ + if(b_is_chroma) + { + s_dims.i4_abscissa = (PAD_LEN_UV_H * 4); + s_dims.i4_ordinate = (PAD_LEN_UV_V * 4); + } + else + { + s_dims.i4_abscissa = (PAD_LEN_Y_H * 2); + s_dims.i4_ordinate = (PAD_LEN_Y_V * 4); + } + + return s_dims; +} + +WORD32 imvcd_get_ref_pic_pad_offset(WORD32 i4_stride, bool b_is_chroma) +{ + return !b_is_chroma ? (i4_stride * PAD_LEN_Y_V * 2 + PAD_LEN_Y_H) + : (i4_stride * PAD_LEN_UV_V * 2 + PAD_LEN_UV_H * 2); +} + +UWORD32 imvcd_get_next_bits(dec_bit_stream_t *ps_bitstream) +{ + UWORD32 u4_next_word; + + NEXTBITS(u4_next_word, ps_bitstream->u4_ofst, ps_bitstream->pu4_buffer, 32); + + return u4_next_word; +} + +void imvcd_set_view_buf_id_to_buf_map(dec_struct_t *ps_view_ctxt) +{ + WORD32 i, j; + + memset(ps_view_ctxt->apv_buf_id_pic_buf_map, 0, sizeof(ps_view_ctxt->apv_buf_id_pic_buf_map)); + + for(i = 0; i < 2; i++) + { + for(j = 0; j < ps_view_ctxt->ps_cur_slice->u1_num_ref_idx_lx_active[i]; j++) + { + ps_view_ctxt + ->apv_buf_id_pic_buf_map[ps_view_ctxt->ps_ref_pic_buf_lx[i][j]->u1_pic_buf_id] = + (void *) ps_view_ctxt->ps_ref_pic_buf_lx[i][j]; + } + } +} + +IV_API_CALL_STATUS_T imvcd_get_next_display_au_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + mvc_au_buffer_t *ps_au_buf; + + IV_API_CALL_STATUS_T e_retval = IV_FAIL; + + UWORD32 i; + WORD32 i4_buf_id; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + ps_au_buf = + (mvc_au_buffer_t *) ih264_disp_mgr_get(&ps_mvcd_ctxt->s_mvc_disp_buf_mgr, &i4_buf_id); + + ps_view_ctxt->i4_display_index = DEFAULT_POC; + + if(ps_au_buf != NULL) + { + ps_view_ctxt->pv_disp_sei_params = &ps_au_buf->s_sei_pic; + ps_view_ctxt->i4_display_index = ps_au_buf->i4_poc; + ps_view_ctxt->u4_num_fld_in_frm += 2; + ps_view_ctxt->s_disp_op.u4_ts = ps_au_buf->u4_time_stamp; + + e_retval = IV_SUCCESS; + } + + if(ps_au_buf) + { + for(i = 0; i < ps_mvcd_ctxt->u2_num_views; i++) + { + yuv_buf_props_t *ps_src = &ps_au_buf->as_view_buffers[i]; + yuv_buf_props_t *ps_dst = &ps_mvcd_ctxt->s_out_buffer.as_view_buf_props[i]; + + WORD32 i4_y_src_stride = ps_src->as_component_bufs[Y].i4_data_stride; + WORD32 i4_uv_src_stride = ps_src->as_component_bufs[UV].i4_data_stride; + UWORD8 *pu1_y_src = (UWORD8 *) ps_src->as_component_bufs[Y].pv_data; + UWORD8 *pu1_uv_src = (UWORD8 *) ps_src->as_component_bufs[UV].pv_data; + + pu1_y_src += (0 == i) ? ps_view_ctxt->u2_crop_offset_y + : (ps_au_buf->as_disp_offsets[i].u2_left_offset + + ps_au_buf->as_disp_offsets[i].u2_top_offset * i4_y_src_stride); + pu1_uv_src += + (0 == i) ? ps_view_ctxt->u2_crop_offset_uv + : (ps_au_buf->as_disp_offsets[i].u2_left_offset + + (ps_au_buf->as_disp_offsets[i].u2_top_offset * i4_uv_src_stride) / 2); + + ps_dst->u2_width = ps_au_buf->u2_disp_width; + ps_dst->u2_height = ps_au_buf->u2_disp_height; + + ASSERT(ps_dst->as_component_bufs[U].i4_data_stride == + ps_dst->as_component_bufs[V].i4_data_stride); + + ih264d_fmt_conv_420sp_to_420p( + pu1_y_src, pu1_uv_src, (UWORD8 *) ps_dst->as_component_bufs[Y].pv_data, + (UWORD8 *) ps_dst->as_component_bufs[U].pv_data, + (UWORD8 *) ps_dst->as_component_bufs[V].pv_data, ps_dst->u2_width, + ps_dst->u2_height, i4_y_src_stride, i4_uv_src_stride, + ps_dst->as_component_bufs[Y].i4_data_stride, + ps_dst->as_component_bufs[U].i4_data_stride, 1, 0); + } + + ih264_buf_mgr_release(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, + ps_au_buf->i4_pic_buf_id, BUF_MGR_IO); + } + + return e_retval; +} + +UWORD32 imvcd_get_num_mbs_in_level(UWORD8 u1_level_idc) +{ + switch(u1_level_idc) + { + case H264_LEVEL_1_0: + { + return MAX_MBS_LEVEL_10; + } + case H264_LEVEL_1_1: + { + return MAX_MBS_LEVEL_11; + } + case H264_LEVEL_1_2: + { + return MAX_MBS_LEVEL_12; + } + case H264_LEVEL_1_3: + { + return MAX_MBS_LEVEL_13; + } + case H264_LEVEL_2_0: + { + return MAX_MBS_LEVEL_20; + } + case H264_LEVEL_2_1: + { + return MAX_MBS_LEVEL_21; + } + case H264_LEVEL_2_2: + { + return MAX_MBS_LEVEL_22; + } + case H264_LEVEL_3_0: + { + return MAX_MBS_LEVEL_30; + } + case H264_LEVEL_3_1: + { + return MAX_MBS_LEVEL_31; + } + case H264_LEVEL_3_2: + { + return MAX_MBS_LEVEL_32; + } + case H264_LEVEL_4_0: + { + return MAX_MBS_LEVEL_40; + } + case H264_LEVEL_4_1: + { + return MAX_MBS_LEVEL_41; + } + case H264_LEVEL_4_2: + { + return MAX_MBS_LEVEL_42; + } + case H264_LEVEL_5_0: + { + return MAX_MBS_LEVEL_50; + } + case H264_LEVEL_5_1: + default: + { + return MAX_MBS_LEVEL_51; + } + } +} + +WORD16 imvcd_free_dynamic_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_deblk_pic); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_dec_mb_map); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_recon_mb_map); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu2_slice_num_map); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_dec_slice_buf); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_frm_mb_info); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pi2_coeff_data); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_parse_mb_data); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_parse_part_params); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_deblk_top_mb); + + if(ps_view_ctxt->p_ctxt_inc_mb_map) + { + ps_view_ctxt->p_ctxt_inc_mb_map -= 1; + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->p_ctxt_inc_mb_map); + } + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_mv_p[0]); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_mv_p[1]); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_pred_pkd); + { + UWORD8 i; + for(i = 0; i < MV_SCRATCH_BUFS; i++) + { + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_mv_top_p[i]); + } + } + + if(ps_view_ctxt->pu1_y_intra_pred_line) + { + ps_view_ctxt->pu1_y_intra_pred_line -= MB_SIZE; + } + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_y_intra_pred_line); + + if(ps_view_ctxt->pu1_u_intra_pred_line) + { + ps_view_ctxt->pu1_u_intra_pred_line -= MB_SIZE; + } + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_u_intra_pred_line); + + if(ps_view_ctxt->pu1_v_intra_pred_line) + { + ps_view_ctxt->pu1_v_intra_pred_line -= MB_SIZE; + } + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->pu1_v_intra_pred_line); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_view_ctxt->ps_nbr_mb_row); + + PS_DEC_ALIGNED_FREE(ps_view_ctxt, ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_au_buf_base); + PS_DEC_ALIGNED_FREE(ps_view_ctxt, + ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_au_mv_pred_buf_base); + + return OK; +} + +static UWORD32 imvcd_get_num_au_data_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + return ps_view_ctxt->u1_pic_bufs; +} + +static UWORD32 imvcd_get_num_elements_in_mv_pred_buf(UWORD32 u4_view_wd, UWORD32 u4_view_ht) +{ + return (u4_view_wd * (u4_view_ht + PAD_MV_BANK_ROW)) / MB_SIZE; +} + +static UWORD32 imvcd_get_mv_pred_buf_padding_length(UWORD32 u4_view_wd) +{ + return (u4_view_wd * OFFSET_MV_BANK_ROW) / MB_SIZE; +} + +static UWORD32 imvcd_get_au_mv_pred_buf_size(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UWORD32 u4_num_bufs = imvcd_get_num_au_data_bufs(ps_mvcd_ctxt); + + UWORD32 u4_size = 0; + + u4_size += sizeof(mvc_au_mv_pred_t); + + u4_size += + imvcd_get_num_elements_in_mv_pred_buf(ps_view_ctxt->u2_pic_wd, ps_view_ctxt->u2_pic_ht) * + (sizeof(mv_pred_t) + sizeof(UWORD8)); + + u4_size *= u4_num_bufs; + u4_size *= ps_mvcd_ctxt->u2_num_views; + + return u4_size; +} + +static UWORD32 imvcd_get_au_buf_size(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UWORD32 u4_size = 0; + UWORD32 u4_num_bufs = imvcd_get_num_au_data_bufs(ps_mvcd_ctxt); + + u4_size += sizeof(mvc_au_buffer_t); + + /* All rvalues below incorporate both padding and pic dimensions */ + u4_size += ALIGN64(ps_view_ctxt->u2_frm_wd_y * ps_view_ctxt->u2_frm_ht_y) * sizeof(UWORD8); + u4_size += ALIGN64(ps_view_ctxt->u2_frm_wd_uv * ps_view_ctxt->u2_frm_ht_uv) * sizeof(UWORD8); + + u4_size *= ps_mvcd_ctxt->u2_num_views; + u4_size *= u4_num_bufs; + + return u4_size; +} + +WORD32 imvcd_init_au_buffers(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + UWORD32 i, j; + UWORD32 u4_luma_size, u4_chroma_size; + WORD32 i4_error_code; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + WORD64 i8_alloc_mem_size = imvcd_get_au_buf_size(ps_mvcd_ctxt); + UWORD8 *pu1_buf = (UWORD8 *) ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_au_buf_base; + UWORD32 u4_num_bufs = imvcd_get_num_au_data_bufs(ps_mvcd_ctxt); + + if(ps_mvcd_ctxt->u2_num_views > MAX_NUM_VIEWS) + { + ps_view_ctxt->i4_error_code = ERROR_BUF_MGR; + return ERROR_BUF_MGR; + } + + u4_luma_size = ps_view_ctxt->u2_frm_wd_y * ps_view_ctxt->u2_frm_ht_y; + u4_chroma_size = ps_view_ctxt->u2_frm_wd_uv * ps_view_ctxt->u2_frm_ht_uv; + + for(i = 0; i < u4_num_bufs; i++) + { + WORD32 i4_stride; + + mvc_au_buffer_t *ps_au_buf = (mvc_au_buffer_t *) pu1_buf; + + pu1_buf += sizeof(ps_au_buf[0]); + + for(j = 0; j < ps_mvcd_ctxt->u2_num_views; j++) + { + i4_stride = ps_view_ctxt->u2_frm_wd_y; + ps_au_buf->as_view_buffers[j].as_component_bufs[Y].i4_data_stride = i4_stride; + ps_au_buf->as_view_buffers[j].as_component_bufs[Y].pv_data = + pu1_buf + imvcd_get_ref_pic_pad_offset(i4_stride, false); + pu1_buf += ALIGN64(u4_luma_size) * sizeof(pu1_buf[0]); + i8_alloc_mem_size -= ALIGN64(u4_luma_size) * sizeof(pu1_buf[0]); + + i4_stride = ps_view_ctxt->u2_frm_wd_uv; + ps_au_buf->as_view_buffers[j].as_component_bufs[UV].i4_data_stride = i4_stride; + ps_au_buf->as_view_buffers[j].as_component_bufs[UV].pv_data = + pu1_buf + imvcd_get_ref_pic_pad_offset(i4_stride, true); + pu1_buf += ALIGN64(u4_chroma_size) * sizeof(pu1_buf[0]); + i8_alloc_mem_size -= ALIGN64(u4_chroma_size) * sizeof(pu1_buf[0]); + + ps_au_buf->as_view_buffers[j].as_component_bufs[V].pv_data = NULL; + + ps_au_buf->as_view_buffers[j].u2_height = + ps_view_ctxt->ps_cur_sps->u2_frm_ht_in_mbs * MB_SIZE; + ps_au_buf->as_view_buffers[j].u2_width = + ps_view_ctxt->ps_cur_sps->u2_frm_wd_in_mbs * MB_SIZE; + ps_au_buf->as_view_buffers[j].u1_bit_depth = 8; + + ASSERT(i8_alloc_mem_size >= 0); + } + + ps_au_buf->i4_pic_buf_id = i; + + i4_error_code = + ih264_buf_mgr_add(ps_mvcd_ctxt->s_mvc_au_buf_mgr.ps_buf_mgr_ctxt, ps_au_buf, i); + + if(0 != i4_error_code) + { + ps_view_ctxt->i4_error_code = ERROR_BUF_MGR; + + return ERROR_BUF_MGR; + } + + ps_mvcd_ctxt->s_mvc_au_buf_mgr.aps_buf_id_to_au_buf_map[i] = ps_au_buf; + } + + return OK; +} + +WORD32 imvcd_init_au_mv_pred_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + UWORD32 i, j; + WORD32 buf_ret; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + UWORD32 u4_width = ps_view_ctxt->u2_pic_wd; + UWORD32 u4_height = ps_view_ctxt->u2_pic_ht; + UWORD32 u4_mode_info_buf_size = imvcd_get_num_elements_in_mv_pred_buf(u4_width, u4_height); + UWORD8 *pu1_buf = ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_au_mv_pred_buf_base; + WORD64 i8_alloc_mem_size = imvcd_get_au_mv_pred_buf_size(ps_mvcd_ctxt); + UWORD32 u4_num_bufs = imvcd_get_num_au_data_bufs(ps_mvcd_ctxt); + + if(ps_mvcd_ctxt->u2_num_views > MAX_NUM_VIEWS) + { + return ERROR_BUF_MGR; + } + + for(i = 0; i < u4_num_bufs; i++) + { + mvc_au_mv_pred_t *ps_au_mv_data = (mvc_au_mv_pred_t *) pu1_buf; + + pu1_buf += sizeof(ps_au_mv_data[0]); + + buf_ret = ih264_buf_mgr_add(ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.ps_buf_mgr_ctxt, + ps_au_mv_data, i); + + if(0 != buf_ret) + { + return ERROR_BUF_MGR; + } + + for(j = 0; j < ps_mvcd_ctxt->u2_num_views; j++) + { + UWORD32 u4_mv_buf_size = u4_mode_info_buf_size * sizeof(ps_au_mv_data->aps_mvs[j][0]); + UWORD32 u4_mode_desc_buf_size = + u4_mode_info_buf_size * sizeof(ps_au_mv_data->apu1_mode_descriptors[j][0]); + + ps_au_mv_data->aps_mvs[j] = (mv_pred_t *) pu1_buf; + ps_au_mv_data->aps_mvs[j] += imvcd_get_mv_pred_buf_padding_length(u4_width); + pu1_buf += u4_mv_buf_size; + i8_alloc_mem_size -= u4_mv_buf_size; + + ps_au_mv_data->apu1_mode_descriptors[j] = pu1_buf; + pu1_buf += u4_mode_desc_buf_size; + i8_alloc_mem_size -= u4_mode_desc_buf_size; + + memset(ps_au_mv_data->aps_mvs[j] - imvcd_get_mv_pred_buf_padding_length(u4_width), 0, + u4_mv_buf_size); + + memset(ps_au_mv_data->apu1_mode_descriptors[j], 0, u4_mode_desc_buf_size); + + ASSERT(i8_alloc_mem_size >= 0); + } + } + + return OK; +} + +WORD32 imvcd_allocate_dynamic_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + dec_seq_params_t *ps_sps = ps_view_ctxt->ps_cur_sps; + + UWORD32 u4_total_mbs = ps_sps->u2_total_num_of_mbs; + UWORD32 u4_wd_mbs = ps_view_ctxt->u2_frm_wd_in_mbs; + UWORD32 u4_ht_mbs = ps_view_ctxt->u2_frm_ht_in_mbs; + const WORD32 i4_default_alignment = 128; + void *pv_mem_ctxt = ps_view_ctxt->pv_mem_ctxt; + + UWORD8 *pu1_buf; + WORD32 i4_mem_size; + WORD32 i; + void *pv_buf; + WORD32 i4_num_entries; + + if(ps_mvcd_ctxt->u2_num_views > MAX_NUM_VIEWS) + { + return IV_FAIL; + } + + i4_mem_size = u4_total_mbs * sizeof(ps_view_ctxt->pu1_dec_mb_map[0]); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu1_dec_mb_map = pv_buf; + + i4_mem_size = u4_total_mbs * sizeof(ps_view_ctxt->pu1_recon_mb_map[0]); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu1_recon_mb_map = pv_buf; + + i4_mem_size = u4_total_mbs * sizeof(ps_view_ctxt->pu2_slice_num_map[0]); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->pu2_slice_num_map = pv_buf; + + ps_view_ctxt->ps_parse_cur_slice = ps_view_ctxt->ps_dec_slice_buf; + ps_view_ctxt->ps_decode_cur_slice = ps_view_ctxt->ps_dec_slice_buf; + ps_view_ctxt->ps_computebs_cur_slice = ps_view_ctxt->ps_dec_slice_buf; + ps_view_ctxt->ps_pred_start = ps_view_ctxt->ps_pred; + + i4_mem_size = sizeof(parse_pmbarams_t) * (ps_view_ctxt->u1_recon_mb_grp); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_parse_mb_data = pv_buf; + + i4_mem_size = sizeof(parse_part_params_t) * ((ps_view_ctxt->u1_recon_mb_grp) << 4); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_parse_part_params = pv_buf; + + i4_mem_size = (u4_wd_mbs * sizeof(deblkmb_neighbour_t)); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_deblk_top_mb = pv_buf; + + i4_mem_size = sizeof(ctxt_inc_mb_info_t) * (u4_wd_mbs + 2); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->p_ctxt_inc_mb_map = pv_buf; + /* 0th entry of CtxtIncMbMap will be always be containing default values + for CABAC context representing MB not available */ + ps_view_ctxt->p_ctxt_inc_mb_map += 1; + + i4_mem_size = sizeof(mv_pred_t) * ps_view_ctxt->u1_recon_mb_grp * 16; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_mv_p[0] = pv_buf; + + i4_mem_size = sizeof(mv_pred_t) * ps_view_ctxt->u1_recon_mb_grp * 16; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_mv_p[1] = pv_buf; + + for(i = 0; i < MV_SCRATCH_BUFS; i++) + { + i4_mem_size = (sizeof(mv_pred_t) * ps_view_ctxt->u1_recon_mb_grp * 4); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_mv_top_p[i] = pv_buf; + } + + i4_mem_size = sizeof(UWORD8) * ((u4_wd_mbs + 2) * MB_SIZE) * 2; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + ps_view_ctxt->pu1_y_intra_pred_line = pv_buf; + memset(ps_view_ctxt->pu1_y_intra_pred_line, 0, i4_mem_size); + ps_view_ctxt->pu1_y_intra_pred_line += MB_SIZE; + + i4_mem_size = sizeof(UWORD8) * ((u4_wd_mbs + 2) * MB_SIZE) * 2; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + ps_view_ctxt->pu1_u_intra_pred_line = pv_buf; + memset(ps_view_ctxt->pu1_u_intra_pred_line, 0, i4_mem_size); + ps_view_ctxt->pu1_u_intra_pred_line += MB_SIZE; + + i4_mem_size = sizeof(UWORD8) * ((u4_wd_mbs + 2) * MB_SIZE) * 2; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + ps_view_ctxt->pu1_v_intra_pred_line = pv_buf; + memset(ps_view_ctxt->pu1_v_intra_pred_line, 0, i4_mem_size); + ps_view_ctxt->pu1_v_intra_pred_line += MB_SIZE; + + if(ps_view_ctxt->u1_separate_parse) + { + /* Needs one extra row of info, to hold top row data */ + i4_mem_size = sizeof(mb_neigbour_params_t) * 2 * ((u4_wd_mbs + 2) * (u4_ht_mbs + 1)); + } + else + { + i4_mem_size = sizeof(mb_neigbour_params_t) * 2 * (u4_wd_mbs + 2); + } + + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + + ps_view_ctxt->ps_nbr_mb_row = pv_buf; + memset(ps_view_ctxt->ps_nbr_mb_row, 0, i4_mem_size); + + i4_mem_size = (u4_total_mbs + u4_wd_mbs) * sizeof(deblk_mb_t); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + ps_view_ctxt->ps_deblk_pic = pv_buf; + memset(ps_view_ctxt->ps_deblk_pic, 0, i4_mem_size); + + i4_mem_size = sizeof(dec_mb_info_t) * u4_total_mbs; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + ps_view_ctxt->ps_frm_mb_info = pv_buf; + memset(ps_view_ctxt->ps_frm_mb_info, 0, i4_mem_size); + + if((1 >= ps_view_ctxt->ps_cur_sps->u1_num_ref_frames) && (0 == ps_view_ctxt->i4_display_delay)) + { + i4_num_entries = 1; + } + else + { + i4_num_entries = MAX_FRAMES; + } + + i4_num_entries = (2 * i4_num_entries) + 1; + i4_num_entries *= 2; + + i4_mem_size = i4_num_entries * sizeof(void *); + i4_mem_size += PAD_MAP_IDX_POC * sizeof(void *); + i4_mem_size *= u4_total_mbs; + i4_mem_size += sizeof(dec_slice_struct_t) * u4_total_mbs; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + + ps_view_ctxt->ps_dec_slice_buf = pv_buf; + memset(ps_view_ctxt->ps_dec_slice_buf, 0, i4_mem_size); + pu1_buf = (UWORD8 *) ps_view_ctxt->ps_dec_slice_buf; + pu1_buf += sizeof(dec_slice_struct_t) * u4_total_mbs; + ps_view_ctxt->pv_map_ref_idx_to_poc_buf = (void *) pu1_buf; + + /* Allocate memory for packed pred info */ + i4_num_entries = u4_total_mbs; + i4_num_entries *= 16 * 2; + + i4_mem_size = sizeof(pred_info_pkd_t) * i4_num_entries; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_view_ctxt->ps_pred_pkd = pv_buf; + + /* Allocate memory for coeff data */ + i4_mem_size = MB_LUM_SIZE * sizeof(WORD16); + /*For I16x16 MBs, 16 4x4 AC coeffs and 1 4x4 DC coeff TU blocks will be sent + For all MBs along with 8 4x4 AC coeffs 2 2x2 DC coeff TU blocks will be sent + So use 17 4x4 TU blocks for luma and 9 4x4 TU blocks for chroma */ + i4_mem_size += u4_total_mbs * + (MAX(17 * sizeof(tu_sblk4x4_coeff_data_t), 4 * sizeof(tu_blk8x8_coeff_data_t)) + + 9 * sizeof(tu_sblk4x4_coeff_data_t)); + // 32 bytes for each mb to store u1_prev_intra4x4_pred_mode and + // u1_rem_intra4x4_pred_mode data + i4_mem_size += u4_total_mbs * 32; + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + + ps_view_ctxt->pi2_coeff_data = pv_buf; + + ps_view_ctxt->pv_pic_tu_coeff_data = (void *) (ps_view_ctxt->pi2_coeff_data + MB_LUM_SIZE); + + i4_mem_size = imvcd_get_au_mv_pred_buf_size(ps_mvcd_ctxt); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_mvcd_ctxt->s_mvc_au_mv_pred_buf_mgr.pv_au_mv_pred_buf_base = pv_buf; + + i4_mem_size = imvcd_get_au_buf_size(ps_mvcd_ctxt); + pv_buf = ps_view_ctxt->pf_aligned_alloc(pv_mem_ctxt, i4_default_alignment, i4_mem_size); + RETURN_IF((NULL == pv_buf), IV_FAIL); + memset(pv_buf, 0, i4_mem_size); + ps_mvcd_ctxt->s_mvc_au_buf_mgr.pv_au_buf_base = pv_buf; + + /***************************************************************************/ + /*Initialize cabac context pointers for every SE that has fixed contextIdx */ + /***************************************************************************/ + { + bin_ctxt_model_t *const p_cabac_ctxt_table_t = ps_view_ctxt->p_cabac_ctxt_table_t; + bin_ctxt_model_t **p_coeff_abs_level_minus1_t = ps_view_ctxt->p_coeff_abs_level_minus1_t; + bin_ctxt_model_t **p_cbf_t = ps_view_ctxt->p_cbf_t; + + ps_view_ctxt->p_mb_field_dec_flag_t = p_cabac_ctxt_table_t + MB_FIELD_DECODING_FLAG; + ps_view_ctxt->p_prev_intra4x4_pred_mode_flag_t = + p_cabac_ctxt_table_t + PREV_INTRA4X4_PRED_MODE_FLAG; + ps_view_ctxt->p_rem_intra4x4_pred_mode_t = p_cabac_ctxt_table_t + REM_INTRA4X4_PRED_MODE; + ps_view_ctxt->p_intra_chroma_pred_mode_t = p_cabac_ctxt_table_t + INTRA_CHROMA_PRED_MODE; + ps_view_ctxt->p_mb_qp_delta_t = p_cabac_ctxt_table_t + MB_QP_DELTA; + ps_view_ctxt->p_ref_idx_t = p_cabac_ctxt_table_t + REF_IDX; + ps_view_ctxt->p_mvd_x_t = p_cabac_ctxt_table_t + MVD_X; + ps_view_ctxt->p_mvd_y_t = p_cabac_ctxt_table_t + MVD_Y; + p_cbf_t[0] = p_cabac_ctxt_table_t + CBF + 0; + p_cbf_t[1] = p_cabac_ctxt_table_t + CBF + 4; + p_cbf_t[2] = p_cabac_ctxt_table_t + CBF + 8; + p_cbf_t[3] = p_cabac_ctxt_table_t + CBF + 12; + p_cbf_t[4] = p_cabac_ctxt_table_t + CBF + 16; + ps_view_ctxt->p_cbp_luma_t = p_cabac_ctxt_table_t + CBP_LUMA; + ps_view_ctxt->p_cbp_chroma_t = p_cabac_ctxt_table_t + CBP_CHROMA; + + p_coeff_abs_level_minus1_t[LUMA_DC_CTXCAT] = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_0_OFFSET; + + p_coeff_abs_level_minus1_t[LUMA_AC_CTXCAT] = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_1_OFFSET; + + p_coeff_abs_level_minus1_t[LUMA_4X4_CTXCAT] = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_2_OFFSET; + + p_coeff_abs_level_minus1_t[CHROMA_DC_CTXCAT] = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_3_OFFSET; + + p_coeff_abs_level_minus1_t[CHROMA_AC_CTXCAT] = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1 + COEFF_ABS_LEVEL_CAT_4_OFFSET; + + p_coeff_abs_level_minus1_t[LUMA_8X8_CTXCAT] = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1_8X8 + COEFF_ABS_LEVEL_CAT_5_OFFSET; + + /********************************************************/ + /* context for the high profile related syntax elements */ + /* This is maintained seperately in s_high_profile */ + /********************************************************/ + { + ps_view_ctxt->s_high_profile.ps_transform8x8_flag = + p_cabac_ctxt_table_t + TRANSFORM_SIZE_8X8_FLAG; + + ps_view_ctxt->s_high_profile.ps_sigcoeff_8x8_frame = + p_cabac_ctxt_table_t + SIGNIFICANT_COEFF_FLAG_8X8_FRAME; + + ps_view_ctxt->s_high_profile.ps_last_sigcoeff_8x8_frame = + p_cabac_ctxt_table_t + LAST_SIGNIFICANT_COEFF_FLAG_8X8_FRAME; + + ps_view_ctxt->s_high_profile.ps_coeff_abs_levelminus1 = + p_cabac_ctxt_table_t + COEFF_ABS_LEVEL_MINUS1_8X8; + + ps_view_ctxt->s_high_profile.ps_sigcoeff_8x8_field = + p_cabac_ctxt_table_t + SIGNIFICANT_COEFF_FLAG_8X8_FIELD; + + ps_view_ctxt->s_high_profile.ps_last_sigcoeff_8x8_field = + p_cabac_ctxt_table_t + LAST_SIGNIFICANT_COEFF_FLAG_8X8_FIELD; + } + } + + return OK; +} + +void imvcd_convert_au_buf_to_view_buf(mvc_au_buffer_t *ps_au_buf, pic_buffer_t *ps_view_buf, + UWORD16 u2_view_order_id, UWORD16 u2_view_id) +{ + yuv_buf_props_t *ps_view_buffer = &ps_au_buf->as_view_buffers[u2_view_id]; + offsets_t *ps_disp_offsets = &ps_au_buf->as_disp_offsets[u2_view_id]; + mvc_au_mv_pred_t *ps_au_mv_data = ps_au_buf->ps_au_mv_data; + + ps_view_buf->pu1_buf1 = ps_view_buffer->as_component_bufs[Y].pv_data; + ps_view_buf->pu1_buf2 = ps_view_buffer->as_component_bufs[UV].pv_data; + ps_view_buf->pu1_buf3 = NULL; + ps_view_buf->u2_frm_wd_y = ps_view_buffer->as_component_bufs[Y].i4_data_stride; + ps_view_buf->u2_frm_wd_uv = ps_view_buffer->as_component_bufs[UV].i4_data_stride; + ps_view_buf->pu1_buf3 = NULL; + + ps_view_buf->u2_disp_width = ps_au_buf->u2_disp_width; + ps_view_buf->u2_disp_height = ps_au_buf->u2_disp_height; + ps_view_buf->u2_frm_ht_y = ps_view_buffer->u2_height; + ps_view_buf->u2_frm_ht_uv = ps_view_buffer->u2_height / 2; + + ps_view_buf->u4_time_stamp = ps_au_buf->u4_time_stamp; + ps_view_buf->u4_ts = ps_au_buf->u4_time_stamp; + + ps_view_buf->u2_crop_offset_y = + ps_disp_offsets->u2_left_offset + ps_disp_offsets->u2_top_offset * ps_view_buf->u2_frm_wd_y; + ps_view_buf->u2_crop_offset_uv = + ps_disp_offsets->u2_left_offset + + (ps_disp_offsets->u2_top_offset / 2) * ps_view_buf->u2_frm_wd_uv; + + ps_view_buf->i4_poc = ps_au_buf->i4_poc; + ps_view_buf->i4_pic_num = ps_au_buf->i4_frame_num; + ps_view_buf->i4_frame_num = ps_au_buf->i4_frame_num; + ps_view_buf->i4_avg_poc = ps_au_buf->i4_poc; + ps_view_buf->u1_is_short = ps_au_buf->b_is_short_term_ref; + ps_view_buf->u1_pic_type = ps_au_buf->u1_pic_type; + ps_view_buf->i4_top_field_order_cnt = ps_au_buf->i4_poc; + ps_view_buf->i4_bottom_field_order_cnt = ps_au_buf->i4_poc; + ps_view_buf->u1_picturetype = FRM_PIC; + ps_view_buf->u1_long_term_frm_idx = ps_au_buf->u1_long_term_frm_idx; + ps_view_buf->u1_long_term_pic_num = ps_au_buf->u1_long_term_pic_num; + ps_view_buf->u4_pack_slc_typ = ps_au_buf->au4_pack_slc_typ[u2_view_order_id]; + ps_view_buf->u1_pic_struct = ps_au_buf->u1_pic_struct; + ps_view_buf->s_sei_pic = ps_au_buf->s_sei_pic; + + ps_view_buf->u1_pic_buf_id = ps_au_buf->i4_pic_buf_id; + ps_view_buf->u1_mv_buf_id = ps_au_buf->i4_mv_buf_id; + + ps_view_buf->pu1_col_zero_flag = ps_au_mv_data->apu1_mode_descriptors[u2_view_id]; + ps_view_buf->ps_mv = ps_au_mv_data->aps_mvs[u2_view_id]; +} + +void imvcd_init_ref_idx_to_ref_buf_map(mvc_dec_ctxt_t *ps_mvcd_ctxt) +{ + pic_buffer_t *ps_pic; + + void **ppv_map_ref_idx_to_poc_lx; + WORD8 i, j; + + dec_struct_t *ps_view_ctxt = &ps_mvcd_ctxt->s_view_dec_ctxt; + + bool b_is_b_pic = !!( + ps_mvcd_ctxt->ps_cur_au->au4_pack_slc_typ[ps_mvcd_ctxt->u2_num_views_decoded] & B_SLC_BIT); + + for(i = 0; i < 1 + ((WORD32) b_is_b_pic); i++) + { + ppv_map_ref_idx_to_poc_lx = + ps_view_ctxt->ppv_map_ref_idx_to_poc + ((0 == i) ? FRM_LIST_L0 : FRM_LIST_L1); + ppv_map_ref_idx_to_poc_lx[0] = NULL; + ppv_map_ref_idx_to_poc_lx++; + + for(j = 0; j < ps_view_ctxt->ps_cur_slice->u1_num_ref_idx_lx_active[i]; j++) + { + ps_pic = ps_view_ctxt->ps_ref_pic_buf_lx[i][j]; + + ppv_map_ref_idx_to_poc_lx[j] = ps_pic->pu1_buf1; + } + } + + if(!b_is_b_pic) + { + ppv_map_ref_idx_to_poc_lx = ps_view_ctxt->ppv_map_ref_idx_to_poc + FRM_LIST_L1; + ppv_map_ref_idx_to_poc_lx[0] = NULL; + } + + if(ps_view_ctxt->u4_num_cores >= 3) + { + WORD32 i4_size; + + WORD32 i4_num_entries = MAX_FRAMES; + + if((1 >= ps_view_ctxt->ps_cur_sps->u1_num_ref_frames) && + (0 == ps_view_ctxt->i4_display_delay)) + { + i4_num_entries = 1; + } + + i4_num_entries = 2 * i4_num_entries + 1; + i4_num_entries *= 2; + + i4_size = i4_num_entries * sizeof(void *); + i4_size += PAD_MAP_IDX_POC * sizeof(void *); + + memcpy(ps_view_ctxt->ps_parse_cur_slice->ppv_map_ref_idx_to_poc, + ps_view_ctxt->ppv_map_ref_idx_to_poc, i4_size); + } +} + +void imvcd_ivp_buf_copier(mvc_au_buffer_t *ps_au_buf_src, mvc_au_buffer_t *ps_au_buf_dst, + mvc_au_mv_pred_t *ps_au_mv_data_src, mvc_au_mv_pred_t *ps_au_mv_data_dst, + UWORD16 u2_src_view_id, UWORD16 u2_dst_view_id) +{ + UWORD32 i, j; + + mv_pred_t *ps_mode_info_src = ps_au_mv_data_src->aps_mvs[u2_src_view_id]; + mv_pred_t *ps_mode_info_dst = ps_au_mv_data_dst->aps_mvs[u2_dst_view_id]; + + UWORD32 u4_view_wd = ps_au_buf_src->as_view_buffers[u2_src_view_id].u2_width; + UWORD32 u4_view_ht = ps_au_buf_src->as_view_buffers[u2_src_view_id].u2_height; + UWORD32 u4_mode_info_buf_size = imvcd_get_num_elements_in_mv_pred_buf(u4_view_wd, u4_view_ht); + UWORD32 u4_mode_info_pad_size = imvcd_get_mv_pred_buf_padding_length(u4_view_wd); + + ps_mode_info_src -= u4_mode_info_pad_size; + ps_mode_info_dst -= u4_mode_info_pad_size; + + ps_au_buf_dst->ps_au_mv_data = ps_au_mv_data_dst; + + ps_au_buf_dst->as_disp_offsets[u2_dst_view_id] = ps_au_buf_src->as_disp_offsets[u2_src_view_id]; + + for(i = 0; i < NUM_SP_COMPONENTS; i++) + { + bool b_is_chroma = ((COMPONENT_TYPES_T) i) != Y; + + coordinates_t s_pad_dims = imvcd_get_buf_pad_dims(b_is_chroma); + buffer_container_t *ps_src = + &ps_au_buf_src->as_view_buffers[u2_src_view_id].as_component_bufs[i]; + buffer_container_t *ps_dst = + &ps_au_buf_dst->as_view_buffers[u2_dst_view_id].as_component_bufs[i]; + + WORD32 i4_src_pad_offset = + imvcd_get_ref_pic_pad_offset(ps_src->i4_data_stride, b_is_chroma); + WORD32 i4_dst_pad_offset = + imvcd_get_ref_pic_pad_offset(ps_dst->i4_data_stride, b_is_chroma); + + for(j = 0; j < ((u4_view_ht >> b_is_chroma) + s_pad_dims.i4_ordinate); j++) + { + UWORD8 *pu1_src = + ((UWORD8 *) ps_src->pv_data) + j * ps_src->i4_data_stride - i4_src_pad_offset; + UWORD8 *pu1_dst = + ((UWORD8 *) ps_dst->pv_data) + j * ps_dst->i4_data_stride - i4_dst_pad_offset; + + memcpy(pu1_dst, pu1_src, (u4_view_wd + s_pad_dims.i4_abscissa) * sizeof(pu1_dst[0])); + } + } + + memcpy(ps_mode_info_dst, ps_mode_info_src, u4_mode_info_buf_size * sizeof(ps_mode_info_dst[0])); + + for(i = 0; i < u4_mode_info_buf_size; i++) + { + /* In accordance with 'H.8.4' */ + ps_au_mv_data_dst->apu1_mode_descriptors[u2_dst_view_id][i] = + ps_au_mv_data_src->apu1_mode_descriptors[u2_src_view_id][i] & 0xFE; + } + + ps_au_buf_dst->au4_pack_slc_typ[u2_dst_view_id] = + ps_au_buf_src->au4_pack_slc_typ[u2_src_view_id]; + ps_au_buf_dst->b_is_short_term_ref = ps_au_buf_src->b_is_short_term_ref; + ps_au_buf_dst->i4_avg_poc = ps_au_buf_src->i4_avg_poc; + ps_au_buf_dst->i4_frame_num = ps_au_buf_src->i4_frame_num; + ps_au_buf_dst->i4_pic_num = ps_au_buf_src->i4_pic_num; + ps_au_buf_dst->i4_poc = ps_au_buf_src->i4_poc; + ps_au_buf_dst->s_sei_pic = ps_au_buf_src->s_sei_pic; + ps_au_buf_dst->u1_long_term_frm_idx = ps_au_buf_src->u1_long_term_frm_idx; + ps_au_buf_dst->u1_long_term_pic_num = ps_au_buf_src->u1_long_term_pic_num; + ps_au_buf_dst->u1_picturetype = ps_au_buf_src->u1_picturetype; + ps_au_buf_dst->u1_pic_struct = ps_au_buf_src->u1_pic_struct; + ps_au_buf_dst->u2_disp_height = ps_au_buf_src->u2_disp_height; + ps_au_buf_dst->u2_disp_width = ps_au_buf_src->u2_disp_width; + ps_au_buf_dst->u4_time_stamp = ps_au_buf_src->u4_time_stamp; +} diff --git a/decoder/mvc/imvcd_utils.h b/decoder/mvc/imvcd_utils.h new file mode 100644 index 0000000..ce65854 --- /dev/null +++ b/decoder/mvc/imvcd_utils.h @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +/*****************************************************************************/ +/* */ +/* File Name : imvcd_utils.c */ +/* */ +/* Description : MVCD Utility functions used by 'imvcd_api.c' */ +/* */ +/*****************************************************************************/ + +#ifndef _IMVCD_UTILS_H_ +#define _IMVCD_UTILS_H_ + +#include +#include + +#include "ih264_typedefs.h" +#include "imvc_defs.h" +#include "ih264d_mvpred.h" +#include "ih264d_structs.h" +#include "imvcd_structs.h" + +#define SWAP(x, y, data_type) \ + { \ + data_type temp; \ + memcpy(&temp, &y, sizeof(data_type)); \ + memcpy(&y, &x, sizeof(data_type)); \ + memcpy(&x, &temp, sizeof(data_type)); \ + } + +extern IV_API_CALL_STATUS_T imvcd_get_next_display_au_buf(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern UWORD32 imvcd_get_num_mbs_in_level(UWORD8 u1_level_idc); + +extern WORD32 imvcd_allocate_dynamic_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern WORD16 imvcd_free_dynamic_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern WORD32 imvcd_init_au_buffers(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern WORD32 imvcd_init_au_mv_pred_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern void imvcd_convert_au_buf_to_view_buf(mvc_au_buffer_t *ps_au_buf, pic_buffer_t *ps_view_buf, + UWORD16 u2_view_order_id, UWORD16 u2_view_id); + +extern void imvcd_init_ref_idx_to_ref_buf_map(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern void imvcd_ivp_buf_copier(mvc_au_buffer_t *ps_au_buf_src, mvc_au_buffer_t *ps_au_buf_dst, + mvc_au_mv_pred_t *ps_au_mv_data_src, + mvc_au_mv_pred_t *ps_au_mv_data_dst, UWORD16 u2_src_view_id, + UWORD16 u2_dst_view_id); + +/* Function defined in 'ih264d_utils.c' and declared nowhere else */ +extern WORD32 ih264d_init_dec_mb_grp(dec_struct_t *ps_dec); + +extern void ih264d_init_cabac_contexts(UWORD8 u1_slice_type, dec_struct_t *ps_dec); + +extern void ih264d_get_implicit_weights(dec_struct_t *ps_dec); + +extern void imvcd_free_ref_bufs(mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr, + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr, + WORD32 i4_pic_buf_id); + +extern void imvcd_release_all_ref_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt, WORD32 i4_num_bufs); + +extern void imvcd_free_ref_and_io_bufs(mvc_au_buf_mgr_t *ps_mvc_au_buf_mgr, + mvc_au_mv_pred_buf_mgr_t *ps_mvc_au_mv_pred_buf_mgr, + WORD32 i4_pic_buf_id); + +extern void imvcd_release_all_ref_and_io_bufs(mvc_dec_ctxt_t *ps_mvcd_ctxt, WORD32 i4_num_bufs); + +extern bool is_header_decoded(WORD32 i4_header_decoded, AVC_EXT_NALU_ID_T e_nalu_id); + +extern bool is_mvc_nalu(AVC_EXT_NALU_ID_T e_nalu_id); + +extern bool is_slice_nalu_type(AVC_EXT_NALU_ID_T e_nalu_id); + +extern nalu_mvc_ext_t *imvcd_get_cur_nalu_mvc_ext(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern nalu_mvc_ext_t *imvcd_get_nalu_mvc_ext(nalu_mvc_ext_t *ps_nalu_mvc_exts, + UWORD16 u2_num_views_decoded, UWORD16 u2_view_id); + +extern ref_pic_list_mod_data_t *imvcd_get_cur_ref_pic_list_mod_data(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern subset_sps_t *imvcd_get_valid_subset_sps(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern void imvcd_modulate_max_disp_seq(dec_struct_t *ps_view_ctxt); + +extern mv_pred_t imvcd_get_default_mv_pred(void); + +extern UWORD32 imvcd_get_max_num_ivp_refs(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern bool imvcd_is_idr_au(mvc_dec_ctxt_t *ps_mvcd_ctxt); + +extern coordinates_t imvcd_get_buf_pad_dims(bool b_is_chroma); + +extern WORD32 imvcd_get_ref_pic_pad_offset(WORD32 i4_stride, bool b_is_chroma); + +extern UWORD32 imvcd_get_next_bits(dec_bit_stream_t *ps_bitstream); + +extern void imvcd_set_view_buf_id_to_buf_map(dec_struct_t *ps_view_ctxt); + +#endif diff --git a/decoder/mvc/libmvcdec.cmake b/decoder/mvc/libmvcdec.cmake new file mode 100644 index 0000000..4eb7643 --- /dev/null +++ b/decoder/mvc/libmvcdec.cmake @@ -0,0 +1,61 @@ +# src files +list( + APPEND + LIBMVCDEC_SRCS + "${AVC_ROOT}/decoder/ih264d_api.c" + "${AVC_ROOT}/decoder/ih264d_bitstrm.c" + "${AVC_ROOT}/decoder/ih264d_cabac.c" + "${AVC_ROOT}/decoder/ih264d_cabac_init_tables.c" + "${AVC_ROOT}/decoder/ih264d_compute_bs.c" + "${AVC_ROOT}/decoder/ih264d_deblocking.c" + "${AVC_ROOT}/decoder/ih264d_dpb_mgr.c" + "${AVC_ROOT}/decoder/ih264d_format_conv.c" + "${AVC_ROOT}/decoder/ih264d_function_selector_generic.c" + "${AVC_ROOT}/decoder/ih264d_inter_pred.c" + "${AVC_ROOT}/decoder/ih264d_mb_utils.c" + "${AVC_ROOT}/decoder/ih264d_mvpred.c" + "${AVC_ROOT}/decoder/ih264d_nal.c" + "${AVC_ROOT}/decoder/ih264d_parse_bslice.c" + "${AVC_ROOT}/decoder/ih264d_parse_cabac.c" + "${AVC_ROOT}/decoder/ih264d_parse_cavlc.c" + "${AVC_ROOT}/decoder/ih264d_parse_headers.c" + "${AVC_ROOT}/decoder/ih264d_parse_islice.c" + "${AVC_ROOT}/decoder/ih264d_parse_mb_header.c" + "${AVC_ROOT}/decoder/ih264d_parse_pslice.c" + "${AVC_ROOT}/decoder/ih264d_parse_slice.c" + "${AVC_ROOT}/decoder/ih264d_process_bslice.c" + "${AVC_ROOT}/decoder/ih264d_process_intra_mb.c" + "${AVC_ROOT}/decoder/ih264d_process_pslice.c" + "${AVC_ROOT}/decoder/ih264d_quant_scaling.c" + "${AVC_ROOT}/decoder/ih264d_sei.c" + "${AVC_ROOT}/decoder/ih264d_tables.c" + "${AVC_ROOT}/decoder/ih264d_thread_compute_bs.c" + "${AVC_ROOT}/decoder/ih264d_thread_parse_decode.c" + "${AVC_ROOT}/decoder/ih264d_utils.c" + "${AVC_ROOT}/decoder/ih264d_vui.c" + "${AVC_ROOT}/decoder/mvc/imvcd_api.c" + "${AVC_ROOT}/decoder/mvc/imvcd_api_utils.c" + "${AVC_ROOT}/decoder/mvc/imvcd_dpb_manager.c" + "${AVC_ROOT}/decoder/mvc/imvcd_error_handler.c" + "${AVC_ROOT}/decoder/mvc/imvcd_nalu_parser.c" + "${AVC_ROOT}/decoder/mvc/imvcd_slice_functions.c" + "${AVC_ROOT}/decoder/mvc/imvcd_utils.c") + +include_directories(${AVC_ROOT}/decoder) +include_directories(${AVC_ROOT}/decoder/mvc) + +if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "aarch64" OR "${CMAKE_SYSTEM_PROCESSOR}" + STREQUAL "aarch32") + list( + APPEND LIBMVCDEC_ASMS "${AVC_ROOT}/decoder/arm/ih264d_function_selector.c" + "${AVC_ROOT}/decoder/arm/ih264d_function_selector_a9q.c" + "${AVC_ROOT}/decoder/arm/ih264d_function_selector_av8.c") +else() + list( + APPEND LIBMVCDEC_ASMS "${AVC_ROOT}/decoder/x86/ih264d_function_selector.c" + "${AVC_ROOT}/decoder/x86/ih264d_function_selector_sse42.c" + "${AVC_ROOT}/decoder/x86/ih264d_function_selector_ssse3.c") +endif() + +add_library(libmvcdec STATIC ${LIBAVC_COMMON_SRCS} ${LIBAVC_COMMON_ASMS} + ${LIBMVCDEC_SRCS} ${LIBMVCDEC_ASMS}) diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp index 4c83461..e79e31e 100644 --- a/fuzzer/Android.bp +++ b/fuzzer/Android.bp @@ -7,16 +7,10 @@ package { default_applicable_licenses: ["external_libavc_license"], } -cc_fuzz { - name: "avc_dec_fuzzer", - host_supported: true, - srcs: [ - "avc_dec_fuzzer.cpp", - ], - static_libs: [ - "libavcdec", - "liblog", - ], +cc_defaults { + name: "libavc_mvc_fuzzer_defaults", + host_supported:true, + static_libs: ["liblog"], target: { darwin: { enabled: false, @@ -30,6 +24,28 @@ cc_fuzz { }, } +cc_fuzz { + name: "avc_dec_fuzzer", + defaults: ["libavc_mvc_fuzzer_defaults"], + srcs: [ + "avc_dec_fuzzer.cpp", + ], + static_libs: [ + "libavcdec", + ], +} + +cc_fuzz { + name: "mvc_dec_fuzzer", + defaults: ["libavc_mvc_fuzzer_defaults"], + srcs: [ + "mvc_dec_fuzzer.cpp", + ], + static_libs: [ + "libmvcdec", + ], +} + cc_fuzz { name: "avc_enc_fuzzer", host_supported: true, diff --git a/fuzzer/README.md b/fuzzer/README.md index f848629..0e7c189 100644 --- a/fuzzer/README.md +++ b/fuzzer/README.md @@ -36,6 +36,7 @@ Create a directory CORPUS_DIR and copy some elementary h264 files To run the fuzzers ``` $ ./avc_dec_fuzzer CORPUS_DIR +$ ./mvc_dec_fuzzer CORPUS_DIR $ ./avc_enc_fuzzer CORPUS_DIR ``` @@ -45,6 +46,7 @@ $ ./avc_enc_fuzzer CORPUS_DIR Build the fuzzers ``` $ mm -j$(nproc) avc_dec_fuzzer + $ mm -j$(nproc) mvc_dec_fuzzer $ mm -j$(nproc) avc_enc_fuzzer ``` @@ -58,6 +60,11 @@ To run avc_dec_fuzzer on device $ adb sync data $ adb shell /data/fuzz/arm64/avc_dec_fuzzer/avc_dec_fuzzer CORPUS_DIR ``` +To run mvc_dec_fuzzer on device +``` + $ adb sync data + $ adb shell /data/fuzz/arm64/mvc_dec_fuzzer/mvc_dec_fuzzer CORPUS_DIR +``` To run avc_enc_fuzzer on device ``` $ adb sync data @@ -69,6 +76,11 @@ To run avc_dec_fuzzer on host $ $ANDROID_HOST_OUT/fuzz/x86_64/avc_dec_fuzzer/avc_dec_fuzzer CORPUS_DIR ``` +To run mvc_dec_fuzzer on host +``` + $ $ANDROID_HOST_OUT/fuzz/x86_64/mvc_dec_fuzzer/mvc_dec_fuzzer CORPUS_DIR +``` + To run avc_enc_fuzzer on host ``` $ $ANDROID_HOST_OUT/fuzz/x86_64/avc_enc_fuzzer/avc_enc_fuzzer CORPUS_DIR diff --git a/fuzzer/mvc_dec_fuzzer.cmake b/fuzzer/mvc_dec_fuzzer.cmake new file mode 100644 index 0000000..469d62e --- /dev/null +++ b/fuzzer/mvc_dec_fuzzer.cmake @@ -0,0 +1,2 @@ +libavc_add_fuzzer(mvc_dec_fuzzer libmvcdec SOURCES + "${AVC_ROOT}/fuzzer/mvc_dec_fuzzer.cpp") diff --git a/fuzzer/mvc_dec_fuzzer.cpp b/fuzzer/mvc_dec_fuzzer.cpp new file mode 100644 index 0000000..8bb1330 --- /dev/null +++ b/fuzzer/mvc_dec_fuzzer.cpp @@ -0,0 +1,416 @@ +/****************************************************************************** + * + * Copyright (C) 2019 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#include "ih264_typedefs.h" +#include "imvcd.h" +} +#endif + +#define MAX_NUM_VIEWS 6 + +#define NUM_COMPONENTS 3 + +#define NELEMENTS(x) (sizeof(x) / sizeof(x[0])) + +typedef enum ARG_OFFSETS_T +{ + OFFSET_COLOR_FORMAT = 6, + OFFSET_NUM_CORES, + OFFSET_ARCH, + /* Should be the last entry */ + OFFSET_MAX, +} ARG_OFFSETS_T; + +static const IV_COLOR_FORMAT_T supportedColorFormats[] = {IV_YUV_420P}; +static const IVD_ARCH_T supportedArchitectures[] = {ARCH_ARM_NEONINTR, ARCH_X86_GENERIC, + ARCH_X86_SSSE3, ARCH_X86_SSE42}; +static const int kMaxNumDecodeCalls = 1000; +static const int kSupportedColorFormats = NELEMENTS(supportedColorFormats); +static const int kSupportedArchitectures = NELEMENTS(supportedArchitectures); +static const int kMaxCores = 3; + +static inline void *mvcd_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size) +{ + void *buf = nullptr; + (void) pv_ctxt; + + if(0 != posix_memalign(&buf, alignment, i4_size)) + { + return nullptr; + } + + return buf; +} + +static inline void mvcd_aligned_free(void *pv_ctxt, void *pv_buf) +{ + (void) pv_ctxt; + free(pv_buf); +} + +class Codec +{ + public: + Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores); + ~Codec(); + + void resetCodec(); + WORD32 allocFrame(); + void freeFrame(); + IV_API_CALL_STATUS_T decodeHeader(const uint8_t *data, size_t size); + IV_API_CALL_STATUS_T decodeFrame(const uint8_t *data, size_t size, size_t *bytesConsumed); + void setArchitecture(IVD_ARCH_T arch); + void setBufInfo(); + void setCores(); + + ivd_out_bufdesc_t *getOutBuf() { return &mOutBufHandle; } + + iv_yuv_buf_t *getViewDispBuf(UWORD16 u2_view_id = 0) { return &as_view_disp_bufs[u2_view_id]; } + + UWORD32 getNumViews() { return mBufInfo.s_mvc_buf_info.u2_num_views; } + + iv_obj_t *getCodecHandle() { return mCodec; } + + private: + iv_obj_t *mCodec; + ivd_out_bufdesc_t mOutBufHandle; + iv_yuv_buf_t as_view_disp_bufs[MAX_NUM_VIEWS]; + imvcd_get_buf_info_op_t mBufInfo; + IV_COLOR_FORMAT_T mColorFormat; + size_t mNumCores; + uint32_t mWidth; + uint32_t mHeight; +}; + +Codec::Codec(IV_COLOR_FORMAT_T colorFormat, size_t numCores) + : mCodec(nullptr), mColorFormat(colorFormat), mNumCores(numCores), mWidth(0), mHeight(0) +{ + imvcd_create_ip_t s_create_ip; + imvcd_create_op_t s_create_op; + + s_create_ip.s_ivd_ip.e_cmd = IVD_CMD_CREATE; + s_create_ip.s_ivd_ip.e_output_format = colorFormat; + s_create_ip.s_ivd_ip.pf_aligned_alloc = mvcd_aligned_malloc; + s_create_ip.s_ivd_ip.pf_aligned_free = mvcd_aligned_free; + s_create_ip.s_ivd_ip.u4_share_disp_buf = 0; + s_create_ip.s_ivd_ip.pv_mem_ctxt = nullptr; + + s_create_ip.s_ivd_ip.u4_size = sizeof(s_create_ip.s_ivd_ip); + s_create_op.s_ivd_op.u4_size = sizeof(s_create_op.s_ivd_op); + + imvcd_api_function(NULL, &s_create_ip, &s_create_op); + + mCodec = static_cast(s_create_op.s_ivd_op.pv_handle); + + setCores(); + + memset(getOutBuf(), 0, sizeof(getOutBuf()[0])); +} + +Codec::~Codec() +{ + imvcd_delete_ip_t s_delete_ip; + imvcd_delete_op_t s_delete_op; + + s_delete_ip.s_ivd_ip.e_cmd = IVD_CMD_DELETE; + + s_delete_ip.s_ivd_ip.u4_size = sizeof(s_delete_ip.s_ivd_ip); + s_delete_op.s_ivd_op.u4_size = sizeof(s_delete_op.s_ivd_op); + + imvcd_api_function(mCodec, &s_delete_ip, &s_delete_op); +} + +void Codec::setCores() +{ + imvcd_set_num_cores_ip_t s_ctl_ip; + imvcd_set_num_cores_op_t s_ctl_op; + + s_ctl_ip.u4_size = sizeof(s_ctl_ip); + s_ctl_op.u4_size = sizeof(s_ctl_op); + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = static_cast(IMVCD_CTL_SET_NUM_CORES); + s_ctl_ip.u4_num_cores = mNumCores; + + imvcd_api_function(mCodec, &s_ctl_ip, &s_ctl_op); +} + +void Codec::setArchitecture(IVD_ARCH_T e_arch) +{ + imvcd_set_arch_ip_t s_ctl_ip; + imvcd_set_arch_op_t s_ctl_op; + + s_ctl_ip.u4_size = sizeof(s_ctl_ip); + s_ctl_op.u4_size = sizeof(s_ctl_op); + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = static_cast(IMVCD_CTL_SET_PROCESSOR); + s_ctl_ip.e_arch = e_arch; + s_ctl_ip.e_soc = SOC_GENERIC; + + imvcd_api_function(mCodec, &s_ctl_ip, &s_ctl_op); +} + +void Codec::setBufInfo() +{ + imvcd_get_buf_info_ip_t s_ctl_ip; + imvcd_get_buf_info_op_t s_ctl_op; + + s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip); + s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op); + s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.s_ivd_ip.e_sub_cmd = + static_cast(IVD_CMD_CTL_GETBUFINFO); + + imvcd_api_function(mCodec, &s_ctl_ip, &s_ctl_op); + + mBufInfo = s_ctl_op; +} + +WORD32 Codec::allocFrame() +{ + if(getNumViews() > MAX_NUM_VIEWS) + { + return IV_FAIL; + } + + if(mBufInfo.s_ivd_op.u4_min_num_out_bufs < (NUM_COMPONENTS * getNumViews())) + { + return IV_FAIL; + } + + getOutBuf()->u4_num_bufs = mBufInfo.s_ivd_op.u4_min_num_out_bufs; + + for(UWORD32 i = 0; i < getOutBuf()->u4_num_bufs; i++) + { + getOutBuf()->u4_min_out_buf_size[i] = mBufInfo.s_ivd_op.u4_min_out_buf_size[i]; + getOutBuf()->pu1_bufs[i] = + (UWORD8 *) mvcd_aligned_malloc(nullptr, 16, mBufInfo.s_ivd_op.u4_min_out_buf_size[i]); + + if(getOutBuf()->pu1_bufs[i] == nullptr) + { + return IV_FAIL; + } + } + + return IV_SUCCESS; +} + +void Codec::freeFrame() +{ + for(UWORD32 i = 0; i < getOutBuf()->u4_num_bufs; i++) + { + if(getOutBuf()->pu1_bufs[i]) + { + mvcd_aligned_free(nullptr, getOutBuf()->pu1_bufs[i]); + getOutBuf()->pu1_bufs[i] = nullptr; + } + } +} + +static void sendDecodeSignal(iv_obj_t *psCodec, IVD_VIDEO_DECODE_MODE_T eDecMode) +{ + imvcd_set_config_ip_t s_ctl_ip; + imvcd_set_config_op_t s_ctl_op; + + s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip); + s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op); + s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.s_ivd_ip.e_sub_cmd = + static_cast(IVD_CMD_CTL_SETPARAMS); + + s_ctl_ip.s_ivd_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.s_ivd_ip.e_frm_skip_mode = IVD_SKIP_NONE; + s_ctl_ip.s_ivd_ip.e_vid_dec_mode = eDecMode; + + imvcd_api_function(psCodec, &s_ctl_ip, &s_ctl_op); +} + +IV_API_CALL_STATUS_T Codec::decodeHeader(const uint8_t *data, size_t size) +{ + IV_API_CALL_STATUS_T ret; + + WORD32 numBytesRemaining = size; + + sendDecodeSignal(mCodec, IVD_DECODE_HEADER); + + while(size > 0) + { + imvcd_video_decode_ip_t s_video_decode_ip; + imvcd_video_decode_op_t s_video_decode_op; + + UWORD32 u4_num_bytes_dec = 0; + + memset(&s_video_decode_ip, 0, sizeof(s_video_decode_ip)); + memset(&s_video_decode_op, 0, sizeof(s_video_decode_op)); + + s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.s_ivd_ip.u4_ts = 0; + s_video_decode_ip.s_ivd_ip.pv_stream_buffer = + static_cast(const_cast(data)); + s_video_decode_ip.s_ivd_ip.u4_num_Bytes = numBytesRemaining; + s_video_decode_ip.s_ivd_ip.s_out_buffer = getOutBuf()[0]; + s_video_decode_op.ps_view_disp_bufs = getViewDispBuf(); + + s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip); + s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op); + + ret = imvcd_api_function(mCodec, &s_video_decode_ip, &s_video_decode_op); + + if(IV_SUCCESS != ret) + { + return IV_FAIL; + } + + u4_num_bytes_dec = s_video_decode_op.s_ivd_op.u4_num_bytes_consumed; + + data += u4_num_bytes_dec; + numBytesRemaining -= u4_num_bytes_dec; + mWidth = s_video_decode_op.s_ivd_op.u4_pic_wd; + mHeight = s_video_decode_op.s_ivd_op.u4_pic_ht; + + /* Break after successful header decode */ + if(mWidth && mHeight) + { + break; + } + } + + /* if width / height are invalid, set them to defaults */ + if(!mWidth) + { + mWidth = 1920; + } + + if(!mHeight) + { + mHeight = 1080; + } + + setBufInfo(); + + return IV_SUCCESS; +} + +IV_API_CALL_STATUS_T Codec::decodeFrame(const uint8_t *data, size_t size, size_t *bytesConsumed) +{ + imvcd_video_decode_ip_t s_video_decode_ip; + imvcd_video_decode_op_t s_video_decode_op; + + IV_API_CALL_STATUS_T ret; + + memset(&s_video_decode_ip, 0, sizeof(s_video_decode_ip)); + memset(&s_video_decode_op, 0, sizeof(s_video_decode_op)); + + sendDecodeSignal(mCodec, IVD_DECODE_FRAME); + + s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.s_ivd_ip.u4_ts = 0; + s_video_decode_ip.s_ivd_ip.pv_stream_buffer = static_cast(const_cast(data)); + s_video_decode_ip.s_ivd_ip.u4_num_Bytes = size; + s_video_decode_ip.s_ivd_ip.s_out_buffer = getOutBuf()[0]; + s_video_decode_op.ps_view_disp_bufs = getViewDispBuf(); + + s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip); + s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op); + + ret = imvcd_api_function(mCodec, &s_video_decode_ip, &s_video_decode_op); + + bytesConsumed[0] = s_video_decode_op.s_ivd_op.u4_num_bytes_consumed; + + if(s_video_decode_op.s_ivd_op.u4_pic_wd && s_video_decode_op.s_ivd_op.u4_pic_ht && + ((mWidth != s_video_decode_op.s_ivd_op.u4_pic_wd) || + (mHeight != s_video_decode_op.s_ivd_op.u4_pic_ht))) + { + mWidth = s_video_decode_op.s_ivd_op.u4_pic_wd; + mHeight = s_video_decode_op.s_ivd_op.u4_pic_ht; + freeFrame(); + allocFrame(); + } + + return ret; +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) +{ + if(size < 1) + { + return 0; + } + + WORD32 ret; + + size_t colorFormatOfst = std::min((size_t) OFFSET_COLOR_FORMAT, size - 1); + size_t numCoresOfst = std::min((size_t) OFFSET_NUM_CORES, size - 1); + size_t architectureOfst = std::min((size_t) OFFSET_ARCH, size - 1); + size_t architectureIdx = data[architectureOfst] % kSupportedArchitectures; + size_t colorFormatIdx = data[colorFormatOfst] % kSupportedColorFormats; + uint32_t numCores = (data[numCoresOfst] % kMaxCores) + 1; + uint32_t numDecodeCalls = 0; + + IVD_ARCH_T arch = (IVD_ARCH_T) supportedArchitectures[architectureIdx]; + IV_COLOR_FORMAT_T colorFormat = (IV_COLOR_FORMAT_T) (supportedColorFormats[colorFormatIdx]); + + Codec cCodec = Codec(colorFormat, numCores); + + cCodec.setArchitecture(arch); + + ret = cCodec.decodeHeader(data, size); + + if(IV_SUCCESS != ret) + { + return 0; + } + + ret = cCodec.allocFrame(); + + if(IV_SUCCESS != ret) + { + cCodec.freeFrame(); + + return 0; + } + + while((size > 0) && (numDecodeCalls < kMaxNumDecodeCalls)) + { + size_t bytesConsumed; + + IV_API_CALL_STATUS_T ret = cCodec.decodeFrame(data, size, &bytesConsumed); + + if(ret != IV_SUCCESS) + { + break; + } + + bytesConsumed = std::min(size, bytesConsumed); + data += bytesConsumed; + size -= bytesConsumed; + numDecodeCalls++; + } + + cCodec.freeFrame(); + + return 0; +} diff --git a/test/Android.bp b/test/Android.bp index b859f49..61a9e26 100644 --- a/test/Android.bp +++ b/test/Android.bp @@ -7,8 +7,8 @@ package { default_applicable_licenses: ["external_libavc_license"], } -cc_test { - name: "avcdec", +cc_defaults { + name: "libavc_mvc_app_defaults", gtest: false, host_supported:true, cflags: [ @@ -19,11 +19,6 @@ cc_test { "-Wall", "-Werror", ], - local_include_dirs: [ - "decoder/", - ], - srcs: ["decoder/main.c"], - static_libs: ["libavcdec"], shared_libs: ["liblog"], target: { darwin: { @@ -32,6 +27,28 @@ cc_test { }, } +cc_test { + name: "avcdec", + defaults: ["libavc_mvc_app_defaults"], + local_include_dirs: [ + "decoder/", + ], + srcs: ["decoder/main.c"], + static_libs: ["libavcdec"], +} + +cc_test { + name: "mvcdec", + defaults: ["libavc_mvc_app_defaults"], + local_include_dirs: [ + "mvcdec/", + ], + srcs: ["mvcdec/main.c"], + static_libs: [ + "libmvcdec", + ], +} + cc_test { name: "avcenc", gtest: false, diff --git a/test/mvcdec/dec.cfg b/test/mvcdec/dec.cfg new file mode 100644 index 0000000..f452ea1 --- /dev/null +++ b/test/mvcdec/dec.cfg @@ -0,0 +1,12 @@ +--input input.h264 +--save_output 0 +--num_frames -1 +--output out.yuv +--chroma_format YUV_420P +--share_display_buf 0 +--num_cores 3 +--loopback 0 +--display 0 +--fps 59.94 +--arch ARM_A9Q +--soc GENERIC diff --git a/test/mvcdec/main.c b/test/mvcdec/main.c new file mode 100644 index 0000000..e5b700f --- /dev/null +++ b/test/mvcdec/main.c @@ -0,0 +1,1544 @@ +/****************************************************************************** + * + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + ***************************************************************************** + * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore + */ + +#include +#include +#include +#include +#include + +#include "ih264_typedefs.h" +#include "iv.h" +#include "ivd.h" +#include "imvcd.h" +#include "ih264_debug.h" +#include "ih264d.h" +#include "ithread.h" + +/* Constants */ +#define DEFAULT_NON_DEGRADE_INTERVAL 4 + +#define MAX_DISP_BUFFERS 64 + +#define STRLENGTH 1000 + +#define PEAK_WINDOW_SIZE 8 + +#define DEFAULT_COLOR_FORMAT IV_YUV_420P + +#define DEFAULT_NUM_CORES 1 + +#define MAX_ARG_SHORTNAME_LENGTH 4 + +#define MAX_ARG_NAME_LENGTH 128 + +#define MAX_ARG_DESC_LENGTH 512 + +#define MAX_NUM_VIEWS 6 + +#undef PROFILE_ENABLE + +/* Macro functions */ +#ifdef PROFILE_ENABLE +#define GETTIME(timer) gettimeofday(timer, NULL); + +#define ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency) \ + s_elapsed_time = ((s_end_timer.tv_sec - s_start_timer.tv_sec) * 1000000) + \ + (s_end_timer.tv_usec - s_start_timer.tv_usec); +#else +#define GETTIME(timer) +#define ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency) +#endif + +/* Typedefs */ +typedef enum ARGUMENT_T +{ + INVALID, + HELP, + INPUT_FILE, + OUTPUT, + CHKSUM, + SAVE_OUTPUT, + SAVE_CHKSUM, + NUM_FRAMES, + NUM_CORES, + DISABLE_DEBLOCK_LEVEL, + LOOPBACK, + CONFIG, + DEGRADE_TYPE, + DEGRADE_PICS, + ARCH +} ARGUMENT_T; + +typedef enum COMPONENT_TYPES_T +{ + Y = 0, + UV = 1, + U = 1, + V = 2, + NUM_SP_COMPONENTS = 2, + NUM_COMPONENTS = 3 +} COMPONENT_TYPES_T; + +#ifdef PROFILE_ENABLE +typedef struct timeval TIMER; +#else +typedef WORD32 TIMER; +#endif + +typedef struct mvc_app_files_t +{ + UWORD8 au1_ip_fname[STRLENGTH]; + + UWORD8 au1_op_fname[STRLENGTH]; + + UWORD8 au1_op_chksum_fname[STRLENGTH]; + + UWORD32 au4_disp_frm_id_queue[MAX_DISP_BUFFERS]; +} mvc_app_files_t; + +typedef struct mvc_dec_ctx_t +{ + mvc_app_files_t s_mvc_app_files; + + imvcd_get_buf_info_op_t s_disp_buf_props; + + iv_yuv_buf_t as_view_disp_bufs[MAX_NUM_VIEWS]; + + iv_obj_t *ps_codec_obj; + + IV_COLOR_FORMAT_T e_output_chroma_format; + + IVD_ARCH_T e_arch; + + IVD_SOC_T e_soc; + + UWORD32 u4_max_frm_ts; + + UWORD32 u4_disable_dblk_level; + + WORD32 i4_degrade_type; + + WORD32 i4_degrade_pics; + + UWORD32 u4_num_cores; + + UWORD32 u4_disp_delay; + + UWORD32 u4_fps; + + UWORD32 u4_pic_wd; + + UWORD32 u4_pic_ht; + + UWORD32 u4_loopback; + + UWORD32 u4_file_save_flag; + + UWORD32 u4_chksum_save_flag; + + UWORD8 u1_quit; + +} mvc_dec_ctx_t; + +typedef struct argument_t +{ + UWORD8 au1_argument_shortname[MAX_ARG_SHORTNAME_LENGTH]; + + UWORD8 au1_argument_name[MAX_ARG_NAME_LENGTH]; + + ARGUMENT_T e_argument; + + UWORD8 au1_description[MAX_ARG_DESC_LENGTH]; + +} argument_t; + +/* Function declarations */ +#ifndef MD5_DISABLE +void calc_md5_cksum(UWORD8 *pu1_inbuf, UWORD32 u4_stride, UWORD32 u4_width, UWORD32 u4_height, + UWORD8 *pu1_cksum_p); +#else +#define calc_md5_cksum(a, b, c, d, e) +#endif + +static inline void *mvcd_aligned_malloc(void *pv_ctxt, WORD32 alignment, WORD32 i4_size) +{ + void *buf = NULL; + (void) pv_ctxt; + if(0 != posix_memalign(&buf, alignment, i4_size)) + { + return NULL; + } + return buf; +} + +static inline void mvcd_aligned_free(void *pv_ctxt, void *pv_buf) +{ + (void) pv_ctxt; + free(pv_buf); + return; +} + +static const argument_t argument_mapping[] = { + {"-h", "--help", HELP, "Print this help\n"}, + {"-c", "--config", CONFIG, "config file (Default: test.cfg)\n"}, + {"-i", "--input", INPUT_FILE, "Input file\n"}, + {"-o", "--output", OUTPUT, "Output file\n"}, + {"--", "--chksum", CHKSUM, "Output MD5 Checksum file\n"}, + {"-s", "--save_output", SAVE_OUTPUT, "Save Output file\n"}, + {"--", "--save_chksum", SAVE_CHKSUM, "Save Check sum file\n"}, + {"-n", "--num_frames", NUM_FRAMES, "Number of frames to be decoded\n"}, + {"--", "--num_cores", NUM_CORES, "Number of cores to be used\n"}, + {"--", "--disable_deblock_level", DISABLE_DEBLOCK_LEVEL, + "Disable deblocking level : 0 to 4 - 0 Enable deblocking 4 Disable " + "deblocking completely\n"}, + {"--", "--u4_loopback", LOOPBACK, "Enable playback in a loop\n"}, + {"--", "--degrade_type", DEGRADE_TYPE, + "Degrade type : 0: No degrade 0th bit set : Disable SAO 1st bit set : " + "Disable deblocking 2nd bit set : Faster inter prediction filters 3rd bit " + "set : Fastest inter prediction filters\n"}, + {"--", "--degrade_pics", DEGRADE_PICS, + "Degrade pics : 0 : No degrade 1 : Only on non-reference frames 2 : Do " + "not degrade every 4th or key frames 3 : All non-key frames 4 : All " + "frames\n"}, + {"--", "--arch", ARCH, + "Set Architecture. Supported values - ARM_A9Q, ARMV8_GENERIC, " + "X86_GENERIC, X86_SSE4 \n"}, +}; + +#if ANDROID_NDK +/*****************************************************************************/ +/* */ +/* Function Name : raise */ +/* */ +/* Description : Needed as a workaround when the application is built in */ +/* Android NDK. This is an exception to be called for divide*/ +/* by zero error */ +/* */ +/* Inputs : a */ +/* Globals : */ +/* Processing : None */ +/* */ +/* Outputs : */ +/* Returns : */ +/* */ +/* Issues : */ +/* */ +/* Revision History: */ +/* */ +/* DD MM YYYY Author(s) Changes */ +/* 07 09 2012 100189 Initial Version */ +/* */ +/*****************************************************************************/ +static int raise(int a) +{ + printf("Divide by zero\n"); + return 0; +} +#endif + +static void mvcd_print_usage(void) +{ + WORD32 i = 0; + WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t); + + printf("\nUsage:\n"); + + while(i < num_entries) + { + printf("%-32s\t %s", argument_mapping[i].au1_argument_name, + argument_mapping[i].au1_description); + i++; + } +} + +static ARGUMENT_T mvcd_get_argument(char *name) +{ + WORD32 i = 0; + WORD32 num_entries = sizeof(argument_mapping) / sizeof(argument_t); + + while(i < num_entries) + { + if((0 == strcmp((char *) argument_mapping[i].au1_argument_name, name)) || + ((0 == strcmp((char *) argument_mapping[i].au1_argument_shortname, name)) && + (0 != strcmp((char *) argument_mapping[i].au1_argument_shortname, "--")))) + { + return argument_mapping[i].e_argument; + } + i++; + } + + return INVALID; +} + +static void mvcd_exit(UWORD8 *pu1_err_message) +{ + printf("%s\n", pu1_err_message); + exit(-1); +} + +static void mvcd_parse_argument(mvc_dec_ctx_t *ps_app_ctx, char *argument, char *value) +{ + ARGUMENT_T arg; + + arg = mvcd_get_argument((char *) argument); + + switch(arg) + { + case HELP: + { + mvcd_print_usage(); + + exit(-1); + } + case INPUT_FILE: + { + sscanf(value, "%s", ps_app_ctx->s_mvc_app_files.au1_ip_fname); + + break; + } + case OUTPUT: + { + sscanf(value, "%s", ps_app_ctx->s_mvc_app_files.au1_op_fname); + + break; + } + case CHKSUM: + { + sscanf(value, "%s", ps_app_ctx->s_mvc_app_files.au1_op_chksum_fname); + + break; + } + case SAVE_OUTPUT: + { + sscanf(value, "%u", &ps_app_ctx->u4_file_save_flag); + + break; + } + case SAVE_CHKSUM: + { + sscanf(value, "%u", &ps_app_ctx->u4_chksum_save_flag); + + break; + } + case NUM_FRAMES: + { + sscanf(value, "%u", &ps_app_ctx->u4_max_frm_ts); + + break; + } + case NUM_CORES: + { + sscanf(value, "%u", &ps_app_ctx->u4_num_cores); + + break; + } + case DEGRADE_PICS: + { + sscanf(value, "%d", &ps_app_ctx->i4_degrade_pics); + + break; + } + case DEGRADE_TYPE: + { + sscanf(value, "%d", &ps_app_ctx->i4_degrade_type); + + break; + } + case LOOPBACK: + { + sscanf(value, "%u", &ps_app_ctx->u4_loopback); + + break; + } + case ARCH: + { + if((strcmp(value, "ARM_A9Q")) == 0) + { + ps_app_ctx->e_arch = ARCH_ARM_A9Q; + } + else if((strcmp(value, "X86_GENERIC")) == 0) + { + ps_app_ctx->e_arch = ARCH_X86_GENERIC; + } + else if((strcmp(value, "X86_SSSE3")) == 0) + { + ps_app_ctx->e_arch = ARCH_X86_SSSE3; + } + else if((strcmp(value, "X86_SSE42")) == 0) + { + ps_app_ctx->e_arch = ARCH_X86_SSE42; + } + else if((strcmp(value, "ARMV8_GENERIC")) == 0) + { + ps_app_ctx->e_arch = ARCH_ARMV8_GENERIC; + } + else + { + printf("\nInvalid Arch. Setting it to ARCH_ARMV8_GENERIC\n"); + ps_app_ctx->e_arch = ARCH_ARMV8_GENERIC; + } + + break; + } + case DISABLE_DEBLOCK_LEVEL: + { + sscanf(value, "%u", &ps_app_ctx->u4_disable_dblk_level); + + break; + } + default: + { + printf("Ignoring argument : %s\n", argument); + + break; + } + } +} + +static void mvcd_read_cfg_file(mvc_dec_ctx_t *ps_app_ctx, FILE *ps_cfg_file) +{ + char line[STRLENGTH]; + char description[STRLENGTH]; + char value[STRLENGTH]; + char argument[STRLENGTH]; + void *ret; + + while(0 == feof(ps_cfg_file)) + { + line[0] = '\0'; + ret = fgets(line, STRLENGTH, ps_cfg_file); + if(NULL == ret) break; + argument[0] = '\0'; + /* Reading Input File Name */ + sscanf(line, "%s %s %s", argument, value, description); + if(argument[0] == '\0') continue; + + mvcd_parse_argument(ps_app_ctx, argument, value); + } +} + +static void mvcd_get_view_file_name(const UWORD8 *pu1_default_name, UWORD8 *pu1_view_file_name, + UWORD16 u2_view_id) +{ + CHAR *apc_sub_str[2]; + CHAR ac_string[STRLENGTH]; + + const CHAR ac_delimiters[] = "."; + + strcpy(ac_string, (char *) pu1_default_name); + + apc_sub_str[0] = strtok(ac_string, ac_delimiters); + apc_sub_str[1] = strtok(NULL, ac_delimiters); + + ASSERT(NULL == strtok(NULL, ac_delimiters)); + ASSERT((strlen(apc_sub_str[0]) + strlen(apc_sub_str[1]) + 3) < STRLENGTH); + + sprintf((char *) pu1_view_file_name, "%s_%d.%s", apc_sub_str[0], u2_view_id, apc_sub_str[1]); +} + +static IV_API_CALL_STATUS_T mvcd_in_buf_alloc(mvc_dec_ctx_t *ps_app_ctxt, UWORD8 **ppu1_bs_buf) +{ + ppu1_bs_buf[0] = + (UWORD8 *) malloc(ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_in_buf_size[0]); + + if(ppu1_bs_buf[0] == NULL) + { + return IV_FAIL; + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_in_buf_free(UWORD8 *pu1_bs_buf) +{ + free(pu1_bs_buf); + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_out_buf_alloc(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf) +{ + UWORD32 i; + + UWORD16 u2_num_views = ps_app_ctxt->s_disp_buf_props.s_mvc_buf_info.u2_num_views; + + if(ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_num_out_bufs < (NUM_COMPONENTS * u2_num_views)) + { + return IV_FAIL; + } + + ps_out_buf->u4_num_bufs = ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_num_out_bufs; + + for(i = 0; i < ps_out_buf->u4_num_bufs; i++) + { + ps_out_buf->u4_min_out_buf_size[i] = + ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_out_buf_size[i]; + ps_out_buf->pu1_bufs[i] = + (UWORD8 *) malloc(ps_app_ctxt->s_disp_buf_props.s_ivd_op.u4_min_out_buf_size[i]); + + if(ps_out_buf->pu1_bufs[i] == NULL) + { + return IV_FAIL; + } + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_out_buf_free(ivd_out_bufdesc_t *ps_out_buf) +{ + UWORD32 i; + + for(i = 0; i < ps_out_buf->u4_num_bufs; i++) + { + free(ps_out_buf->pu1_bufs[i]); + } + + return IV_SUCCESS; +} + +static void mvcd_output_write_stall(UWORD8 *au1_fname, UWORD32 u4_cur_frm_idx) +{ + FILE *fp_fast_file = NULL; + + const UWORD8 threshold = 64; + char past_fname[1000]; + + if(u4_cur_frm_idx >= threshold) + { + sprintf(past_fname, (char *) au1_fname, u4_cur_frm_idx - threshold); + do + { + fp_fast_file = fopen(past_fname, "rb"); + + if(fp_fast_file != NULL) + { + fclose(fp_fast_file); + /* Wait until the resource is released by a third party app*/ + ithread_sleep(5000); + } + else + { + break; + } + } while(1); + } +} + +static IV_API_CALL_STATUS_T mvcd_create_decoder(mvc_dec_ctx_t *ps_app_ctxt) +{ + imvcd_create_ip_t s_create_ip; + imvcd_create_op_t s_create_op; + + IV_API_CALL_STATUS_T ret; + + s_create_ip.s_ivd_ip.e_cmd = IVD_CMD_CREATE; + s_create_ip.s_ivd_ip.e_output_format = ps_app_ctxt->e_output_chroma_format; + s_create_ip.s_ivd_ip.pf_aligned_alloc = mvcd_aligned_malloc; + s_create_ip.s_ivd_ip.pf_aligned_free = mvcd_aligned_free; + s_create_ip.s_ivd_ip.u4_share_disp_buf = 0; + s_create_ip.s_ivd_ip.pv_mem_ctxt = NULL; + + s_create_ip.s_ivd_ip.u4_size = sizeof(s_create_ip.s_ivd_ip); + s_create_op.s_ivd_op.u4_size = sizeof(s_create_op.s_ivd_op); + + ret = imvcd_api_function(NULL, &s_create_ip, &s_create_op); + + if(ret != IV_SUCCESS) + { + return ret; + } + + ps_app_ctxt->ps_codec_obj = (iv_obj_t *) s_create_op.s_ivd_op.pv_handle; + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_set_decode_mode(mvc_dec_ctx_t *ps_app_ctxt, + IVD_VIDEO_DECODE_MODE_T e_decode_mode) +{ + imvcd_set_config_ip_t s_ctl_ip; + imvcd_set_config_op_t s_ctl_op; + + s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip); + s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op); + s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.s_ivd_ip.e_sub_cmd = (WORD32) IVD_CMD_CTL_SETPARAMS; + s_ctl_ip.s_ivd_ip.e_frm_out_mode = IVD_DISPLAY_FRAME_OUT; + s_ctl_ip.s_ivd_ip.e_frm_skip_mode = IVD_SKIP_NONE; + s_ctl_ip.s_ivd_ip.e_vid_dec_mode = e_decode_mode; + + return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op); +} + +static IV_API_CALL_STATUS_T mvcd_set_num_cores(mvc_dec_ctx_t *ps_app_ctxt) +{ + imvcd_set_num_cores_ip_t s_ctl_ip; + imvcd_set_num_cores_op_t s_ctl_op; + + s_ctl_ip.u4_size = sizeof(s_ctl_ip); + s_ctl_op.u4_size = sizeof(s_ctl_op); + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = (WORD32) IMVCD_CTL_SET_NUM_CORES; + s_ctl_ip.u4_num_cores = ps_app_ctxt->u4_num_cores; + + return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op); +} + +static IV_API_CALL_STATUS_T mvcd_set_arch(mvc_dec_ctx_t *ps_app_ctxt) +{ + imvcd_set_arch_ip_t s_ctl_ip; + imvcd_set_arch_op_t s_ctl_op; + + s_ctl_ip.u4_size = sizeof(s_ctl_ip); + s_ctl_op.u4_size = sizeof(s_ctl_op); + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = (WORD32) IMVCD_CTL_SET_PROCESSOR; + s_ctl_ip.e_arch = ps_app_ctxt->e_arch; + s_ctl_ip.e_soc = ps_app_ctxt->e_soc; + + return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op); +} + +static IV_API_CALL_STATUS_T mvcd_dump_output(mvc_dec_ctx_t *ps_app_ctxt, + iv_yuv_buf_t *ps_view_disp_bufs, FILE **pps_op_file, + FILE **pps_op_chksum_file, UWORD16 u2_num_views) +{ + UWORD32 i, j; + + UWORD32 u4_file_save = ps_app_ctxt->u4_file_save_flag; + UWORD32 u4_chksum_save = ps_app_ctxt->u4_chksum_save_flag; + + if(!u4_file_save && !u4_chksum_save) + { + return IV_SUCCESS; + } + + if(NULL == ps_view_disp_bufs->pv_y_buf) + { + return IV_FAIL; + } + + for(i = 0; i < u2_num_views; i++) + { + iv_yuv_buf_t *ps_view_buf = &ps_view_disp_bufs[i]; + + if(ps_app_ctxt->e_output_chroma_format == IV_YUV_420P) + { + if(u4_file_save) + { + UWORD8 *pu1_buf = (UWORD8 *) ps_view_buf->pv_y_buf; + UWORD16 u2_width = ps_view_buf->u4_y_wd; + UWORD16 u2_height = ps_view_buf->u4_y_ht; + + for(j = 0; j < u2_height; j++) + { + fwrite(pu1_buf, 1, u2_width, pps_op_file[i]); + + pu1_buf += ps_view_buf->u4_y_strd; + } + + pu1_buf = (UWORD8 *) ps_view_buf->pv_u_buf; + u2_width = ps_view_buf->u4_u_wd; + u2_height = ps_view_buf->u4_u_ht; + + for(j = 0; j < u2_height; j++) + { + fwrite(pu1_buf, 1, u2_width, pps_op_file[i]); + + pu1_buf += ps_view_buf->u4_u_strd; + } + + pu1_buf = (UWORD8 *) ps_view_buf->pv_v_buf; + u2_width = ps_view_buf->u4_v_wd; + u2_height = ps_view_buf->u4_v_ht; + + for(j = 0; j < u2_height; j++) + { + fwrite(pu1_buf, 1, u2_width, pps_op_file[i]); + + pu1_buf += ps_view_buf->u4_v_strd; + } + } + +#ifndef MD5_DISABLE + if(u4_chksum_save) + { + UWORD8 au1_cksum[16]; + + UWORD8 *pu1_buf = (UWORD8 *) ps_view_buf->pv_y_buf; + UWORD16 u2_width = ps_view_buf->u4_y_wd; + UWORD16 u2_height = ps_view_buf->u4_y_ht; + + calc_md5_cksum(pu1_buf, ps_view_buf->u4_y_strd, u2_width, u2_height, au1_cksum); + + fwrite(au1_cksum, sizeof(UWORD8), 16, pps_op_chksum_file[i]); + + pu1_buf = (UWORD8 *) ps_view_buf->pv_u_buf; + u2_width = ps_view_buf->u4_u_wd; + u2_height = ps_view_buf->u4_u_ht; + + calc_md5_cksum(pu1_buf, ps_view_buf->u4_u_strd, u2_width, u2_height, au1_cksum); + + fwrite(au1_cksum, sizeof(UWORD8), 16, pps_op_chksum_file[i]); + + pu1_buf = (UWORD8 *) ps_view_buf->pv_v_buf; + u2_width = ps_view_buf->u4_v_wd; + u2_height = ps_view_buf->u4_v_ht; + + calc_md5_cksum(pu1_buf, ps_view_buf->u4_v_strd, u2_width, u2_height, au1_cksum); + + fwrite(au1_cksum, sizeof(UWORD8), 16, pps_op_chksum_file[i]); + } +#endif + } + else + { + return IV_FAIL; + } + + fflush(pps_op_file[i]); + fflush(pps_op_chksum_file[i]); + } + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_flush(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf, + FILE **pps_op_file, FILE **pps_op_chksum_file, UWORD8 *pu1_bs_buf, + UWORD32 *pu4_op_frm_ts, UWORD32 u4_ip_frm_ts, + UWORD32 u4_bytes_remaining, UWORD16 u2_num_views) +{ + IV_API_CALL_STATUS_T ret = IV_SUCCESS; + + do + { + imvcd_flush_dec_ip_t s_ctl_ip; + imvcd_flush_dec_op_t s_ctl_op; + + if(*(pu4_op_frm_ts) >= u4_ip_frm_ts) + { + break; + } + + s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip); + s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op); + s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.s_ivd_ip.e_sub_cmd = (WORD32) IVD_CMD_CTL_FLUSH; + + ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op); + + if(IV_SUCCESS == ret) + { + imvcd_video_decode_ip_t s_video_decode_ip; + imvcd_video_decode_op_t s_video_decode_op; + + s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.s_ivd_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.s_ivd_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.s_ivd_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.s_ivd_ip.s_out_buffer = ps_out_buf[0]; + s_video_decode_op.ps_view_disp_bufs = ps_app_ctxt->as_view_disp_bufs; + + s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip); + s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op); + + ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_video_decode_ip, + &s_video_decode_op); + + if(1 == s_video_decode_op.s_ivd_op.u4_output_present) + { + ret = mvcd_dump_output(ps_app_ctxt, s_video_decode_op.ps_view_disp_bufs, + pps_op_file, pps_op_chksum_file, u2_num_views); + + (*pu4_op_frm_ts)++; + } + else + { + break; + } + } + } while(IV_SUCCESS == ret); + + return ret; +} + +static IV_API_CALL_STATUS_T mvcd_decode_header(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf, + FILE *ps_ip_file, IVD_ERROR_CODES_T *pe_error_code, + UWORD32 *pu4_num_bytes_dec, UWORD32 u4_ip_frm_ts) +{ + IV_API_CALL_STATUS_T ret; + + UWORD32 u4_ip_buf_len; + UWORD8 *pu1_bs_buf; + + imvcd_video_decode_ip_t s_video_decode_ip = {0}; + imvcd_video_decode_op_t s_video_decode_op = {0}; + + UWORD32 u4_file_pos = 0; + UWORD32 u4_num_bytes_dec = 0; + + ret = mvcd_set_decode_mode(ps_app_ctxt, IVD_DECODE_HEADER); + + if(ret != IV_SUCCESS) + { + pe_error_code[0] = IVD_INIT_DEC_FAILED; + + return ret; + } + + /* Allocate input buffer for header */ + u4_ip_buf_len = 256 * 1024; + pu1_bs_buf = (UWORD8 *) malloc(u4_ip_buf_len); + + if(pu1_bs_buf == NULL) + { + pe_error_code[0] = IVD_MEM_ALLOC_FAILED; + + return IV_FAIL; + } + + do + { + WORD32 u4_numbytes; + UWORD32 u4_bytes_remaining; + + fseek(ps_ip_file, u4_file_pos, SEEK_SET); + u4_numbytes = u4_ip_buf_len; + + u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), u4_numbytes, ps_ip_file); + + if(0 == u4_bytes_remaining) + { + pe_error_code[0] = IVD_UNEXPECTED_END_OF_STREAM; + + return IV_FAIL; + } + + s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.s_ivd_ip.u4_ts = u4_ip_frm_ts; + s_video_decode_ip.s_ivd_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.s_ivd_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.s_ivd_ip.s_out_buffer = ps_out_buf[0]; + s_video_decode_op.ps_view_disp_bufs = ps_app_ctxt->as_view_disp_bufs; + + s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip); + s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op); + + ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_video_decode_ip, &s_video_decode_op); + + if(ret != IV_SUCCESS) + { + pe_error_code[0] = s_video_decode_op.s_ivd_op.u4_error_code; + + return ret; + } + + u4_num_bytes_dec += s_video_decode_op.s_ivd_op.u4_num_bytes_consumed; + +#ifndef PROFILE_ENABLE + printf("%d\n", s_video_decode_op.s_ivd_op.u4_num_bytes_consumed); +#endif + } while(ret != IV_SUCCESS); + + ps_app_ctxt->u4_pic_wd = s_video_decode_op.s_ivd_op.u4_pic_wd; + ps_app_ctxt->u4_pic_ht = s_video_decode_op.s_ivd_op.u4_pic_ht; + + pu4_num_bytes_dec[0] = u4_num_bytes_dec; + pe_error_code[0] = IVD_ERROR_NONE; + + free(pu1_bs_buf); + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_get_buf_info(mvc_dec_ctx_t *ps_app_ctxt) +{ + imvcd_get_buf_info_ip_t s_ctl_ip; + imvcd_get_buf_info_op_t s_ctl_op; + + IV_API_CALL_STATUS_T e_retval; + + s_ctl_ip.s_ivd_ip.u4_size = sizeof(s_ctl_ip.s_ivd_ip); + s_ctl_op.s_ivd_op.u4_size = sizeof(s_ctl_op.s_ivd_op); + s_ctl_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.s_ivd_ip.e_sub_cmd = (WORD32) IVD_CMD_CTL_GETBUFINFO; + + e_retval = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op); + + ps_app_ctxt->s_disp_buf_props = s_ctl_op; + + return e_retval; +} + +static IV_API_CALL_STATUS_T mvcd_set_degrade_type(mvc_dec_ctx_t *ps_app_ctxt) +{ + imvcd_set_degrade_mode_ip_t s_ctl_ip; + imvcd_set_degrade_mode_op_t s_ctl_op; + + s_ctl_ip.u4_size = sizeof(s_ctl_ip); + s_ctl_op.u4_size = sizeof(s_ctl_op); + s_ctl_ip.e_cmd = IVD_CMD_VIDEO_CTL; + s_ctl_ip.e_sub_cmd = (WORD32) IMVCD_CTL_DEGRADE; + s_ctl_ip.i4_degrade_type = ps_app_ctxt->i4_degrade_type; + s_ctl_ip.i4_degrade_pics = ps_app_ctxt->i4_degrade_pics; + s_ctl_ip.i4_nondegrade_interval = DEFAULT_NON_DEGRADE_INTERVAL; + + return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_ctl_ip, &s_ctl_op); +} + +static IV_API_CALL_STATUS_T mvcd_decode_frame(mvc_dec_ctx_t *ps_app_ctxt, ivd_out_bufdesc_t *ps_out_buf, + FILE *ps_ip_file, FILE **pps_op_file, + FILE **pps_op_chksum_file, UWORD8 *pu1_bs_buf, + IVD_ERROR_CODES_T *pe_error_code, + UWORD32 *pu4_num_bytes_consumed, UWORD32 *pu4_file_pos, + UWORD32 *pu4_ip_frm_ts, UWORD32 *pu4_op_frm_ts, + UWORD32 u4_ip_buf_len) +{ + imvcd_video_decode_ip_t s_video_decode_ip; + imvcd_video_decode_op_t s_video_decode_op; +#ifdef PROFILE_ENABLE + TIMER s_start_timer; + TIMER s_end_timer; +#ifdef WINDOWS_TIMER + TIMER frequency; +#endif + + UWORD32 au4_peak_window[PEAK_WINDOW_SIZE]; + UWORD32 s_elapsed_time; +#endif + UWORD32 u4_max_op_frm_ts; + UWORD32 u4_bytes_remaining; + UWORD32 u4_numbytes; + + IV_API_CALL_STATUS_T ret; + + UWORD32 u4_num_bytes_dec = 0; + UWORD16 u2_num_views = ps_app_ctxt->s_disp_buf_props.s_mvc_buf_info.u2_num_views; +#ifdef PROFILE_ENABLE + UWORD32 u4_frm_cnt = 0; + UWORD32 u4_tot_cycles = 0; + UWORD32 u4_tot_fmt_cycles = 0; + UWORD32 u4_peak_window_idx = 0; + UWORD32 u4_peak_avg_max = 0; +#endif + +#ifdef PROFILE_ENABLE + memset(au4_peak_window, 0, sizeof(WORD32) * PEAK_WINDOW_SIZE); + +#ifdef WINDOWS_TIMER + QueryPerformanceFrequency(&frequency); +#endif +#endif + + /*************************************************************************/ + /* Set the decoder in frame decode mode. It was set in header decode */ + /* mode earlier */ + /*************************************************************************/ + ret = mvcd_set_decode_mode(ps_app_ctxt, IVD_DECODE_FRAME); + + if(IV_SUCCESS != ret) + { + pe_error_code[0] = IVD_INIT_DEC_FAILED; + + return ret; + } + + /*************************************************************************/ + /* If required disable deblocking and sao at given level */ + /*************************************************************************/ + ret = mvcd_set_degrade_type(ps_app_ctxt); + + if(IV_SUCCESS != ret) + { + pe_error_code[0] = IVD_INIT_DEC_FAILED; + + return ret; + } + + u4_max_op_frm_ts = ps_app_ctxt->u4_max_frm_ts + ps_app_ctxt->u4_disp_delay; + + if(u4_max_op_frm_ts < ps_app_ctxt->u4_disp_delay) + { + /* clip as overflow has occured*/ + u4_max_op_frm_ts = UINT32_MAX; + } + + if(IV_SUCCESS != ret) + { + pe_error_code[0] = IVD_INIT_DEC_FAILED; + + return ret; + } + + while(pu4_op_frm_ts[0] < u4_max_op_frm_ts) + { + fseek(ps_ip_file, pu4_file_pos[0], SEEK_SET); + u4_numbytes = u4_ip_buf_len; + + u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), u4_numbytes, ps_ip_file); + + if(0 == u4_bytes_remaining) + { + if(ps_app_ctxt->u4_loopback) + { + pu4_file_pos[0] = 0; + + fseek(ps_ip_file, pu4_file_pos[0], SEEK_SET); + u4_numbytes = u4_ip_buf_len; + + u4_bytes_remaining = fread(pu1_bs_buf, sizeof(UWORD8), u4_numbytes, ps_ip_file); + } + else + { + break; + } + } + + s_video_decode_ip.s_ivd_ip.e_cmd = IVD_CMD_VIDEO_DECODE; + s_video_decode_ip.s_ivd_ip.u4_ts = pu4_ip_frm_ts[0]; + s_video_decode_ip.s_ivd_ip.pv_stream_buffer = pu1_bs_buf; + s_video_decode_ip.s_ivd_ip.u4_num_Bytes = u4_bytes_remaining; + s_video_decode_ip.s_ivd_ip.s_out_buffer = ps_out_buf[0]; + s_video_decode_op.ps_view_disp_bufs = ps_app_ctxt->as_view_disp_bufs; + + s_video_decode_ip.s_ivd_ip.u4_size = sizeof(s_video_decode_ip.s_ivd_ip); + s_video_decode_op.s_ivd_op.u4_size = sizeof(s_video_decode_op.s_ivd_op); + + /****************/ + /* Video Decode */ + /****************/ + GETTIME(&s_start_timer); + + ret = imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_video_decode_ip, &s_video_decode_op); + + GETTIME(&s_end_timer); + ELAPSEDTIME(s_start_timer, s_end_timer, s_elapsed_time, frequency); + +#ifdef PROFILE_ENABLE + { + UWORD32 peak_avg, id; + + u4_tot_cycles += s_elapsed_time; + au4_peak_window[u4_peak_window_idx++] = s_elapsed_time; + + if(u4_peak_window_idx == PEAK_WINDOW_SIZE) + { + u4_peak_window_idx = 0; + } + + peak_avg = 0; + for(id = 0; id < PEAK_WINDOW_SIZE; id++) + { + peak_avg += au4_peak_window[id]; + } + + peak_avg /= PEAK_WINDOW_SIZE; + if(peak_avg > u4_peak_avg_max) u4_peak_avg_max = peak_avg; + u4_frm_cnt++; + + printf( + "FrameNum: %4d TimeTaken(microsec): %6d AvgTime: %6d " + "PeakAvgTimeMax: " + "%6d Output: %2d NumBytes: %6d \n", + u4_frm_cnt, s_elapsed_time, u4_tot_cycles / u4_frm_cnt, u4_peak_avg_max, + s_video_decode_op.s_ivd_op.u4_output_present, + s_video_decode_op.s_ivd_op.u4_num_bytes_consumed); + } +#else + printf("%d\n", s_video_decode_op.s_ivd_op.u4_num_bytes_consumed); +#endif + + if(ret != IV_SUCCESS) + { + pe_error_code[0] = s_video_decode_op.s_ivd_op.u4_error_code; + + return ret; + } + + u4_num_bytes_dec = s_video_decode_op.s_ivd_op.u4_num_bytes_consumed; + + pu4_file_pos[0] += u4_num_bytes_dec; + pu4_num_bytes_consumed[0] += u4_num_bytes_dec; + pu4_ip_frm_ts[0]++; + + if(s_video_decode_op.s_ivd_op.u4_output_present) + { + char cur_fname[1000]; + + char *extn = NULL; + + /* The objective is to dump the decoded frames into separate files + * instead of dumping all the frames in one common file. Also, the + * number of dumped frames at any given instance of time cannot exceed + * 'frame_memory' + */ + if(ps_app_ctxt->u4_file_save_flag) + { + /* Locate the position of extension yuv */ + extn = strstr((char *) ps_app_ctxt->s_mvc_app_files.au1_op_fname, "%d"); + + if(extn != NULL) + { + mvcd_output_write_stall(ps_app_ctxt->s_mvc_app_files.au1_op_fname, + pu4_op_frm_ts[0]); + + sprintf(cur_fname, (char *) ps_app_ctxt->s_mvc_app_files.au1_op_fname, + pu4_op_frm_ts[0]); + + pps_op_file[0] = fopen(cur_fname, "wb"); + + if(NULL == pps_op_file[0]) + { + pe_error_code[0] = IVD_MEM_ALLOC_FAILED; + + return IV_FAIL; + } + } + } + + if(u2_num_views > 1) + { + if(s_video_decode_op.ps_view_disp_bufs[0].u4_y_wd != + s_video_decode_op.ps_view_disp_bufs[1].u4_y_wd) + { + pe_error_code[0] = IVD_MEM_ALLOC_FAILED; + + return IV_FAIL; + } + + if(s_video_decode_op.ps_view_disp_bufs[0].u4_y_ht != + s_video_decode_op.ps_view_disp_bufs[1].u4_y_ht) + { + pe_error_code[0] = IVD_MEM_ALLOC_FAILED; + + return IV_FAIL; + } + } + + mvcd_dump_output(ps_app_ctxt, s_video_decode_op.ps_view_disp_bufs, pps_op_file, + pps_op_chksum_file, u2_num_views); + + pu4_op_frm_ts[0]++; + } + else if((s_video_decode_op.s_ivd_op.u4_error_code >> IVD_FATALERROR) & 1) + { + pe_error_code[0] = s_video_decode_op.s_ivd_op.u4_error_code; + + return IV_FAIL; + } + } + +#ifdef PROFILE_ENABLE + printf("Summary\n"); + printf("Input filename : %s\n", ps_app_ctxt->s_mvc_app_files.au1_ip_fname); + printf("Output Width : %-4d\n", ps_app_ctxt->u4_pic_wd); + printf("Output Height : %-4d\n", ps_app_ctxt->u4_pic_ht); + + if(u4_frm_cnt) + { + double avg = u4_tot_cycles / u4_frm_cnt; + double bytes_avg = pu4_num_bytes_consumed[0] / u4_frm_cnt; + double bitrate = (bytes_avg * 8 * ps_app_ctxt->u4_fps) / 1000000; + + printf("Bitrate @ %2d u4_fps(mbps) : %-6.2f\n", ps_app_ctxt->u4_fps, bitrate); + printf("Average decode time(micro sec) : %-6d\n", (WORD32) avg); + printf("Avg Peak decode time(%2d frames) : %-6d\n", PEAK_WINDOW_SIZE, + (WORD32) u4_peak_avg_max); + + avg = (u4_tot_cycles + u4_tot_fmt_cycles) * 1.0 / u4_frm_cnt; + printf("FPS achieved (with format conv) : %-3.2f\n", 1000000 / avg); + } +#endif + + return IV_SUCCESS; +} + +static IV_API_CALL_STATUS_T mvcd_delete_decoder(mvc_dec_ctx_t *ps_app_ctxt) +{ + imvcd_delete_ip_t s_delete_ip; + imvcd_delete_op_t s_delete_op; + + s_delete_ip.s_ivd_ip.e_cmd = IVD_CMD_DELETE; + + s_delete_ip.s_ivd_ip.u4_size = sizeof(s_delete_ip.s_ivd_ip); + s_delete_op.s_ivd_op.u4_size = sizeof(s_delete_op.s_ivd_op); + + return imvcd_api_function(ps_app_ctxt->ps_codec_obj, &s_delete_ip, &s_delete_op); +} + +int main(WORD32 argc, char *argv[]) +{ + mvc_dec_ctx_t s_app_ctxt; + ivd_out_bufdesc_t s_out_buf; + + IV_API_CALL_STATUS_T ret; + IVD_ERROR_CODES_T e_error_code; + + UWORD8 au1_cfg_fname[STRLENGTH]; + UWORD8 au1_error_str[STRLENGTH]; + UWORD32 i; + UWORD32 u4_ip_buf_len; + UWORD32 u4_total_bytes_consumed; + UWORD8 au1_view_file_names[STRLENGTH]; + UWORD16 u2_num_views; + UWORD32 u4_num_header_bytes; + + FILE *ps_cfg_file = NULL; + FILE *ps_ip_file = NULL; + FILE *aps_op_file[MAX_NUM_VIEWS] = {NULL}; + FILE *aps_op_chksum_file[MAX_NUM_VIEWS] = {NULL}; + + UWORD8 *pu1_bs_buf = NULL; + UWORD32 u4_file_pos = 0; + UWORD32 u4_ip_frm_ts = 0, u4_op_frm_ts = 0; + UWORD32 u4_bytes_remaining = 0; + + /* Usage */ + if(argc < 2) + { + mvcd_print_usage(); + + exit(-1); + } + else if(argc == 2) + { + strcpy((char *) au1_cfg_fname, argv[1]); + } + + /***********************************************************************/ + /* Initialize Application parameters */ + /***********************************************************************/ + strcpy((char *) s_app_ctxt.s_mvc_app_files.au1_ip_fname, "\0"); + s_app_ctxt.u4_disp_delay = 0; + s_app_ctxt.u4_max_frm_ts = 100; + s_app_ctxt.u4_loopback = 0; + u4_file_pos = 0; + u4_total_bytes_consumed = 0; + u4_ip_frm_ts = 0; + u4_op_frm_ts = 0; + + s_app_ctxt.u4_num_cores = DEFAULT_NUM_CORES; + s_app_ctxt.i4_degrade_type = 0; + s_app_ctxt.i4_degrade_pics = 0; + s_app_ctxt.e_arch = ARCH_X86_SSE42; + s_app_ctxt.e_soc = SOC_GENERIC; + s_app_ctxt.u1_quit = 0; + s_app_ctxt.u4_disable_dblk_level = 0; + s_app_ctxt.u4_file_save_flag = 0; + s_app_ctxt.u4_chksum_save_flag = 0; + s_app_ctxt.e_output_chroma_format = DEFAULT_COLOR_FORMAT; + + /*************************************************************************/ + /* Parse arguments */ + /*************************************************************************/ + + /* Read command line arguments */ + if(argc > 2) + { + for(i = 1; i < (UWORD32) argc; i += 2) + { + if(CONFIG == mvcd_get_argument(argv[i])) + { + strcpy((char *) au1_cfg_fname, argv[i + 1]); + + if((ps_cfg_file = fopen((char *) au1_cfg_fname, "r")) == NULL) + { + sprintf((char *) au1_error_str, "Could not open Configuration file %s", + au1_cfg_fname); + + mvcd_exit(au1_error_str); + } + mvcd_read_cfg_file(&s_app_ctxt, ps_cfg_file); + fclose(ps_cfg_file); + } + else + { + mvcd_parse_argument(&s_app_ctxt, argv[i], argv[i + 1]); + } + } + } + else + { + if((ps_cfg_file = fopen((char *) au1_cfg_fname, "r")) == NULL) + { + sprintf((char *) au1_error_str, "Could not open Configuration file %s", au1_cfg_fname); + mvcd_exit(au1_error_str); + } + + mvcd_read_cfg_file(&s_app_ctxt, ps_cfg_file); + + fclose(ps_cfg_file); + } + + if(strcmp((char *) s_app_ctxt.s_mvc_app_files.au1_ip_fname, "\0") == 0) + { + printf("\nNo input file given for decoding\n"); + + exit(-1); + } + + /***********************************************************************/ + /* create the file object for input file */ + /***********************************************************************/ + ps_ip_file = fopen((char *) s_app_ctxt.s_mvc_app_files.au1_ip_fname, "rb"); + + if(NULL == ps_ip_file) + { + sprintf((char *) au1_error_str, "Could not open input file %s", + s_app_ctxt.s_mvc_app_files.au1_ip_fname); + + mvcd_exit(au1_error_str); + } + + /***********************************************************************/ + /* create the file object for output file */ + /***********************************************************************/ + /* If the filename does not contain %d, then output will be dumped to + a single file and it is opened here */ + if((1 == s_app_ctxt.u4_file_save_flag) && + (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_fname, "%d") == NULL)) + { + mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_fname, au1_view_file_names, 0); + + aps_op_file[0] = fopen((char *) au1_view_file_names, "wb"); + + if(NULL == aps_op_file[0]) + { + const CHAR au1_explanatory_string[] = "Could not open output file "; + UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1]; + + sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string, au1_view_file_names); + mvcd_exit(au1_error_str); + } + } + + /***********************************************************************/ + /* create the file object for check sum file */ + /***********************************************************************/ + if((1 == s_app_ctxt.u4_chksum_save_flag) && + (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, "%d") == NULL)) + { + mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, au1_view_file_names, + 0); + aps_op_chksum_file[0] = fopen((char *) au1_view_file_names, "wb"); + + if(NULL == aps_op_chksum_file[0]) + { + const CHAR au1_explanatory_string[] = "Could not open check sum file "; + UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1]; + + sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string, au1_view_file_names); + mvcd_exit(au1_error_str); + } + } + + /***************************/ + /* Create decoder instance */ + /***************************/ + ret = mvcd_create_decoder(&s_app_ctxt); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "Error in Create %8x\n", ret); + + mvcd_exit(au1_error_str); + } + + /**************/ + /* set params */ + /**************/ + ret = mvcd_set_decode_mode(&s_app_ctxt, IVD_DECODE_HEADER); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "\nError in Dec mode"); + mvcd_exit(au1_error_str); + } + + /*************************************************************************/ + /* set num of cores */ + /*************************************************************************/ + ret = mvcd_set_num_cores(&s_app_ctxt); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "\nError in setting number of cores"); + mvcd_exit(au1_error_str); + } + + /*************************************************************************/ + /* set processsor */ + /*************************************************************************/ + ret = mvcd_set_arch(&s_app_ctxt); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "\nError in setting Processor type"); + mvcd_exit(au1_error_str); + } + + /*****************/ + /* Header Decode */ + /*****************/ + ret = mvcd_decode_header(&s_app_ctxt, &s_out_buf, ps_ip_file, &e_error_code, + &u4_num_header_bytes, u4_ip_frm_ts); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "Error in header decode 0x%x\n", e_error_code); + mvcd_exit(au1_error_str); + } + + u4_file_pos += u4_num_header_bytes; + u4_total_bytes_consumed += u4_num_header_bytes; + + /****************/ + /* Get buf info */ + /****************/ + ret = mvcd_get_buf_info(&s_app_ctxt); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "Error in Get Buf Info %x", + s_app_ctxt.s_disp_buf_props.s_ivd_op.u4_error_code); + mvcd_exit(au1_error_str); + } + + u2_num_views = s_app_ctxt.s_disp_buf_props.s_mvc_buf_info.u2_num_views; + ASSERT(u2_num_views <= MAX_NUM_VIEWS); + + ret = mvcd_out_buf_alloc(&s_app_ctxt, &s_out_buf); + + if(IV_SUCCESS != ret) + { + sprintf((char *) au1_error_str, "Error in Out buf alloc\n"); + mvcd_exit(au1_error_str); + } + + /***************************************************************************/ + /* create the file object for output file for other views(if present) */ + /***************************************************************************/ + for(i = 1; i < u2_num_views; i++) + { + if((1 == s_app_ctxt.u4_file_save_flag) && + (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_fname, "%d") == NULL)) + { + mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_fname, au1_view_file_names, + i); + + aps_op_file[i] = fopen((char *) au1_view_file_names, "wb"); + + if(NULL == aps_op_file[i]) + { + const UWORD8 au1_explanatory_string[] = "Could not open output file "; + UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1]; + + sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string, + au1_view_file_names); + mvcd_exit(au1_error_str); + } + } + + if((1 == s_app_ctxt.u4_chksum_save_flag) && + (strstr((char *) s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, "%d") == NULL)) + { + mvcd_get_view_file_name(s_app_ctxt.s_mvc_app_files.au1_op_chksum_fname, + au1_view_file_names, i); + aps_op_chksum_file[i] = fopen((char *) au1_view_file_names, "wb"); + + if(NULL == aps_op_chksum_file[i]) + { + const UWORD8 au1_explanatory_string[] = "Could not open check sum file "; + UWORD8 au1_error_str[STRLENGTH + sizeof(au1_explanatory_string) + 1]; + + sprintf((char *) au1_error_str, "%s%s", au1_explanatory_string, + au1_view_file_names); + mvcd_exit(au1_error_str); + } + } + } + + u4_ip_buf_len = s_app_ctxt.s_disp_buf_props.s_ivd_op.u4_min_in_buf_size[0]; + ret = mvcd_in_buf_alloc(&s_app_ctxt, &pu1_bs_buf); + + if(IV_SUCCESS != ret) + { + sprintf((char *) au1_error_str, "Error in In buf alloc\n"); + mvcd_exit(au1_error_str); + } + + ret = mvcd_decode_frame(&s_app_ctxt, &s_out_buf, ps_ip_file, aps_op_file, aps_op_chksum_file, + pu1_bs_buf, &e_error_code, &u4_total_bytes_consumed, &u4_file_pos, + &u4_ip_frm_ts, &u4_op_frm_ts, u4_ip_buf_len); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "Error in Frame decode 0x%x\n", e_error_code); + mvcd_exit(au1_error_str); + } + + /***********************************************************************/ + /* To get the last decoded frames, call process with NULL input */ + /***********************************************************************/ + ret = mvcd_flush(&s_app_ctxt, &s_out_buf, aps_op_file, aps_op_chksum_file, pu1_bs_buf, + &u4_op_frm_ts, u4_ip_frm_ts, u4_bytes_remaining, u2_num_views); + + if(ret != IV_SUCCESS) + { + sprintf((char *) au1_error_str, "\nError in Setting the decoder in flush mode"); + mvcd_exit(au1_error_str); + } + + s_app_ctxt.u1_quit = 1; + + ret = mvcd_delete_decoder(&s_app_ctxt); + + if(IV_SUCCESS != ret) + { + sprintf((char *) au1_error_str, "Error in Codec delete"); + mvcd_exit(au1_error_str); + } + + /***********************************************************************/ + /* Close all the files and free all the memory */ + /***********************************************************************/ + fclose(ps_ip_file); + + for(i = 0; i < u2_num_views; i++) + { + if(aps_op_file[i]) + { + fclose(aps_op_file[i]); + } + + if(aps_op_chksum_file[i]) + { + fclose(aps_op_chksum_file[i]); + } + } + + mvcd_in_buf_free(pu1_bs_buf); + + mvcd_out_buf_free(&s_out_buf); + + return (0); +} diff --git a/test/mvcdec/mvcdec.cmake b/test/mvcdec/mvcdec.cmake new file mode 100644 index 0000000..1b47ca0 --- /dev/null +++ b/test/mvcdec/mvcdec.cmake @@ -0,0 +1,3 @@ +list(APPEND MVC_DEC_APP_SRCS "${AVC_ROOT}/test/mvcdec/main.c") + +libavc_add_executable(mvcdec libmvcdec SOURCES ${MVC_DEC_APP_SRCS})