Decoder: MVC decoding support added

Added support for decoding 'Multiview High' profile, corresponding to
profile_idc of 118 in 'Rec. ITU-T H.264 (08/2021)'.

Bug: 232169767
Test: atest CtsMediaV2TestCases

Change-Id: I63256344a8a205e74f2bcebe555f5ba6cc3163d0
This commit is contained in:
Ashwin Natesan 2022-07-12 13:44:22 +05:30
parent 12813f245c
commit 779bbfdb00
33 changed files with 12666 additions and 82 deletions

200
.clang-format Normal file
View file

@ -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: '^<ext/.*\.h>'
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
...

View file

@ -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,

View file

@ -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")

View file

@ -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")

View file

@ -38,6 +38,7 @@
#ifndef _IH264_DEBUG_H_
#define _IH264_DEBUG_H_
#include <assert.h>
#if DEBUG_PRINT

114
common/mvc/imvc_defs.h Normal file
View file

@ -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

164
common/mvc/imvc_structs.h Normal file
View file

@ -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

View file

@ -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

279
decoder/mvc/imvcd.h Normal file
View file

@ -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 <stdbool.h>
#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

1588
decoder/mvc/imvcd_api.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -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 <string.h>
#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);
}

View file

@ -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

37
decoder/mvc/imvcd_defs.h Normal file
View file

@ -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 <stdint.h>
#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

File diff suppressed because it is too large Load diff

View file

@ -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 <string.h>
#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

View file

@ -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;
}

View file

@ -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

View file

@ -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 <string.h>
#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;
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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

234
decoder/mvc/imvcd_structs.h Normal file
View file

@ -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 <stdbool.h>
#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

1139
decoder/mvc/imvcd_utils.c Normal file

File diff suppressed because it is too large Load diff

121
decoder/mvc/imvcd_utils.h Normal file
View file

@ -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 <stdbool.h>
#include <string.h>
#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

View file

@ -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})

View file

@ -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,

View file

@ -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

View file

@ -0,0 +1,2 @@
libavc_add_fuzzer(mvc_dec_fuzzer libmvcdec SOURCES
"${AVC_ROOT}/fuzzer/mvc_dec_fuzzer.cpp")

416
fuzzer/mvc_dec_fuzzer.cpp Normal file
View file

@ -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 <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#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<iv_obj_t *>(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<IVD_CONTROL_API_COMMAND_TYPE_T>(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<IVD_CONTROL_API_COMMAND_TYPE_T>(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_CONTROL_API_COMMAND_TYPE_T>(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_CONTROL_API_COMMAND_TYPE_T>(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<void *>(const_cast<uint8_t *>(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<void *>(const_cast<uint8_t *>(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;
}

View file

@ -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,

12
test/mvcdec/dec.cfg Normal file
View file

@ -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

1544
test/mvcdec/main.c Normal file

File diff suppressed because it is too large Load diff

3
test/mvcdec/mvcdec.cmake Normal file
View file

@ -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})