[automerger skipped] decoder: increase intermediate bitstream buffer size am: edc4cac357 -s ours
am skip reason: Merged-In Ifc8cbbdf46ced7dc1586798be111ef6729d0d808 with SHA-1 3cb820f353 is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/external/libmpeg2/+/24527359
Change-Id: I0df35266b63c3fbaebbb1bb7aa95cd0649085f0d
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
new file mode 100644
index 0000000..8d7b327
--- /dev/null
+++ b/.github/workflows/cifuzz.yml
@@ -0,0 +1,27 @@
+name: CIFuzz
+on: [pull_request]
+jobs:
+ Fuzzing:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ sanitizer: [address, memory]
+ steps:
+ - name: Build Fuzzers
+ id: build
+ uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
+ with:
+ oss-fuzz-project-name: 'libmpeg2'
+ language: c++
+ - name: Run Fuzzers
+ uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
+ with:
+ oss-fuzz-project-name: 'libmpeg2'
+ language: c++
+ fuzz-seconds: 600
+ - name: Upload Crash
+ uses: actions/upload-artifact@v3
+ if: failure() && steps.build.outcome == 'success'
+ with:
+ name: artifacts
+ path: ./out/artifacts
diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml
new file mode 100644
index 0000000..0ec6d70
--- /dev/null
+++ b/.github/workflows/cmake.yml
@@ -0,0 +1,23 @@
+name: CMake
+
+on:
+ push:
+ branches: [ "main" ]
+ pull_request:
+ branches: [ "main" ]
+
+env:
+ BUILD_TYPE: Release
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Configure CMake
+ run: cmake -B ${{github.workspace}}/out -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
+
+ - name: Build
+ run: cmake --build ${{github.workspace}}/out --config ${{env.BUILD_TYPE}}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ef4a43..890c6c8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,4 +1,6 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.9.1)
+project(libmpeg2 C CXX)
+enable_language(ASM)
set(MPEG2_ROOT "${CMAKE_CURRENT_SOURCE_DIR}")
set(MPEG2_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}")
@@ -18,12 +20,10 @@
find_package(Threads REQUIRED)
set(CMAKE_STATIC_LIBRARY_PREFIX "")
-if(SANITIZE)
- string(TOLOWER ${SANITIZE} SANITIZE)
-
- set(CMAKE_SANITIZER_C_FLAGS "-fno-omit-frame-pointer -fsanitize=${SANITIZE}")
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_SANITIZER_C_FLAGS}")
-endif()
+include("${MPEG2_ROOT}/cmake/utils.cmake")
+libmpeg2_add_compile_options()
+libmpeg2_add_definitions()
+libmpeg2_set_link_libraries()
list(APPEND LIBMPEG2DEC_SRCS
"${MPEG2_ROOT}/common/impeg2_buf_mgr.c"
@@ -87,9 +87,7 @@
set_target_properties(libmpeg2dec
PROPERTIES COMPILE_FLAGS "${LIBMPEG2DEC_C_FLAGS}")
-list(APPEND MPEG2DEC_SRCS "${MPEG2_ROOT}/test/decoder/main.c")
+libmpeg2_add_executable(mpeg2dec libmpeg2dec SOURCES ${MPEG2_ROOT}/test/decoder/main.c)
+target_compile_definitions(mpeg2dec PRIVATE PROFILE_ENABLE MD5_DISABLE)
-add_executable(mpeg2dec ${MPEG2DEC_SRCS})
-set_target_properties(mpeg2dec
- PROPERTIES COMPILE_FLAGS "-DMD5_DISABLE -DPROFILE_ENABLE")
-target_link_libraries(mpeg2dec libmpeg2dec Threads::Threads)
+libmpeg2_add_fuzzer(mpeg2_dec_fuzzer libmpeg2dec SOURCES ${MPEG2_ROOT}/fuzzer/mpeg2_dec_fuzzer.cpp)
diff --git a/METADATA b/METADATA
index a247cbb..37f8316 100644
--- a/METADATA
+++ b/METADATA
@@ -1,16 +1,19 @@
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update libmpeg2
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+
name: "libmpeg2"
description: "Android fork of the libmpeg2 library."
-
third_party {
url {
type: GIT
value: "https://github.com/ittiam-systems/libmpeg2.git"
}
- version: "9fcdebef07c9f30dc8a64f9236078a4b1caaa8e1"
+ version: "v1.2.0"
license_type: NOTICE
last_upgrade_date {
year: 2023
- month: 03
- day: 04
+ month: 8
+ day: 8
}
}
diff --git a/OWNERS b/OWNERS
index 730f28c..7e9072f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,3 +1,4 @@
# owners for external/libmpeg2
+include platform/frameworks/av:/media/janitors/avic_OWNERS
include platform/frameworks/av:/media/janitors/codec_OWNERS
essick@google.com
diff --git a/cmake/utils.cmake b/cmake/utils.cmake
new file mode 100644
index 0000000..559ebe6
--- /dev/null
+++ b/cmake/utils.cmake
@@ -0,0 +1,114 @@
+include(CheckCXXCompilerFlag)
+
+# Adds compiler options for all targets
+function(libmpeg2_add_compile_options)
+ if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+ add_compile_options(-march=armv8-a)
+ elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch32")
+ add_compile_options(-march=armv7-a -mfpu=neon)
+ else()
+ add_compile_options(-msse4.2 -mno-avx)
+ endif()
+
+ set(CMAKE_REQUIRED_FLAGS -fsanitize=fuzzer-no-link)
+ check_cxx_compiler_flag(-fsanitize=fuzzer-no-link
+ COMPILER_HAS_SANITIZE_FUZZER)
+ unset(CMAKE_REQUIRED_FLAGS)
+
+ if(DEFINED SANITIZE)
+ set(CMAKE_REQUIRED_FLAGS -fsanitize=${SANITIZE})
+ check_cxx_compiler_flag(-fsanitize=${SANITIZE} COMPILER_HAS_SANITIZER)
+ unset(CMAKE_REQUIRED_FLAGS)
+
+ if(NOT COMPILER_HAS_SANITIZER)
+ message(
+ FATAL_ERROR "ERROR: Compiler doesn't support -fsanitize=${SANITIZE}")
+ return()
+ endif()
+ add_compile_options(-fno-omit-frame-pointer -fsanitize=${SANITIZE})
+ endif()
+
+endfunction()
+
+# Adds defintions for all targets
+function(libmpeg2_add_definitions)
+ if(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
+ add_definitions(-DARMV8 -DDEFAULT_ARCH=D_ARCH_ARMV8_GENERIC -DENABLE_NEON)
+ elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch32")
+ add_definitions(-DARMV7 -DDEFAULT_ARCH=D_ARCH_ARM_A9Q -DENABLE_NEON
+ -DDISABLE_NEONINTR)
+ else()
+ add_definitions(-DX86 -DX86_LINUX=1 -DDISABLE_AVX2
+ -DDEFAULT_ARCH=D_ARCH_X86_SSE42)
+ endif()
+endfunction()
+
+# Adds libraries needed for executables
+function(libmpeg2_set_link_libraries)
+ link_libraries(Threads::Threads m)
+endfunction()
+
+# cmake-format: off
+# Adds a target for an executable
+#
+# Arguments:
+# NAME: Name of the executatble
+# LIB: Library that executable depends on
+# SOURCES: Source files
+#
+# Optional Arguments:
+# INCLUDES: Include paths
+# LIBS: Additional libraries
+# FUZZER: flag to specify if the target is a fuzzer binary
+# cmake-format: on
+
+function(libmpeg2_add_executable NAME LIB)
+ set(multi_value_args SOURCES INCLUDES LIBS)
+ set(optional_args FUZZER)
+ cmake_parse_arguments(ARG "${optional_args}" "${single_value_args}"
+ "${multi_value_args}" ${ARGN})
+
+ # Check if compiler supports -fsanitize=fuzzer. If not, skip building fuzzer
+ # binary
+ if(ARG_FUZZER)
+ if(NOT COMPILER_HAS_SANITIZE_FUZZER)
+ message("Compiler doesn't support -fsanitize=fuzzer. Skipping ${NAME}")
+ return()
+ endif()
+ endif()
+
+ add_executable(${NAME} ${ARG_SOURCES})
+ target_include_directories(${NAME} PRIVATE ${ARG_INCLUDES})
+ add_dependencies(${NAME} ${LIB} ${ARG_LIBS})
+
+ target_link_libraries(${NAME} ${LIB} ${ARG_LIBS})
+ if(ARG_FUZZER)
+ target_compile_options(${NAME}
+ PRIVATE $<$<COMPILE_LANGUAGE:CXX>:-std=c++17>)
+ if(DEFINED ENV{LIB_FUZZING_ENGINE})
+ set_target_properties(${NAME} PROPERTIES LINK_FLAGS
+ $ENV{LIB_FUZZING_ENGINE})
+ elseif(DEFINED SANITIZE)
+ set_target_properties(${NAME} PROPERTIES LINK_FLAGS
+ -fsanitize=fuzzer,${SANITIZE})
+ else()
+ set_target_properties(${NAME} PROPERTIES LINK_FLAGS -fsanitize=fuzzer)
+ endif()
+ else()
+ if(DEFINED SANITIZE)
+ set_target_properties(${NAME} PROPERTIES LINK_FLAGS
+ -fsanitize=${SANITIZE})
+ endif()
+ endif()
+endfunction()
+
+# cmake-format: off
+# Adds a target for a fuzzer binary
+# Calls libhevc_add_executable with all arguments with FUZZER set to 1
+# Arguments:
+# Refer to libhevc_add_executable's arguments
+# cmake-format: on
+
+function(libmpeg2_add_fuzzer NAME LIB)
+ libmpeg2_add_executable(${NAME} ${LIB} FUZZER 1 ${ARGV})
+endfunction()
diff --git a/common/ithread.c b/common/ithread.c
index 2a31623..023094f 100644
--- a/common/ithread.c
+++ b/common/ithread.c
@@ -190,7 +190,6 @@
}
-#ifdef KEEP_THREADS_ACTIVE
WORD32 ithread_get_cond_struct_size(void)
{
return (sizeof(pthread_cond_t));
@@ -215,4 +214,3 @@
{
return pthread_cond_signal((pthread_cond_t *)cond);
}
-#endif
diff --git a/common/ithread.h b/common/ithread.h
index dd17b0b..6170ef8 100644
--- a/common/ithread.h
+++ b/common/ithread.h
@@ -78,7 +78,6 @@
WORD32 ithread_set_affinity(WORD32 core_id);
-#ifdef KEEP_THREADS_ACTIVE
WORD32 ithread_get_cond_struct_size(void);
WORD32 ithread_cond_init(void *cond);
@@ -88,6 +87,5 @@
WORD32 ithread_cond_wait(void *cond, void *mutex);
WORD32 ithread_cond_signal(void *cond);
-#endif
#endif /* __ITHREAD_H__ */
diff --git a/decoder/impeg2d.h b/decoder/impeg2d.h
index 97094dc..01089b6 100644
--- a/decoder/impeg2d.h
+++ b/decoder/impeg2d.h
@@ -206,6 +206,11 @@
*/
UWORD32 u4_deinterlace;
+ /**
+ * enabling threads
+ */
+ UWORD32 u4_keep_threads_active;
+
} impeg2d_fill_mem_rec_ip_t;
typedef struct
@@ -243,6 +248,11 @@
*/
UWORD32 u4_deinterlace;
+ /**
+ * enable_threads
+ */
+ UWORD32 u4_keep_threads_active;
+
} impeg2d_init_ip_t;
typedef struct
diff --git a/decoder/impeg2d_api.h b/decoder/impeg2d_api.h
index 9cf41be..c64c22b 100644
--- a/decoder/impeg2d_api.h
+++ b/decoder/impeg2d_api.h
@@ -49,11 +49,7 @@
-#ifdef KEEP_THREADS_ACTIVE
#define THREADS_ACTIVE_MEM_RECORDS (2 * MAX_THREADS)
-#else
-#define THREADS_ACTIVE_MEM_RECORDS 0
-#endif
#define NUM_MEM_RECORDS (4 * MAX_THREADS + NUM_INT_FRAME_BUFFERS + \
5 + 2 + 1 + THREADS_ACTIVE_MEM_RECORDS)
diff --git a/decoder/impeg2d_api_main.c b/decoder/impeg2d_api_main.c
index 626e493..22901b3 100644
--- a/decoder/impeg2d_api_main.c
+++ b/decoder/impeg2d_api_main.c
@@ -559,7 +559,6 @@
ps_mem_rec++;
u1_no_rec++;
-#ifdef KEEP_THREADS_ACTIVE
/* To store start/done mutex */
ps_mem_rec->u4_mem_alignment = 8 /* 8 byte alignment*/;
ps_mem_rec->e_mem_type = IV_EXTERNAL_CACHEABLE_PERSISTENT_MEM;
@@ -579,7 +578,6 @@
ps_mem_rec++;
u1_no_rec++;
-#endif
/*************************************************************************/
/* Fill the memory requirement for Motion Compensation Buffers */
@@ -979,6 +977,45 @@
}
+WORD32 impeg2d_join_threads(dec_state_multi_core_t *ps_dec_state_multi_core)
+{
+ dec_state_t *ps_dec_thd, *ps_dec_state;
+
+ ps_dec_state = ps_dec_state_multi_core->ps_dec_state[0];
+
+ if(ps_dec_state->i4_threads_active)
+ {
+ int i;
+ for(i = 0; i < MAX_THREADS; i++)
+ {
+ WORD32 ret;
+ ps_dec_thd = ps_dec_state_multi_core->ps_dec_state[i];
+ if(ps_dec_state_multi_core->au4_thread_launched[i])
+ {
+ ret = ithread_mutex_lock(ps_dec_thd->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret) return(IV_FAIL);
+
+ // set process start for the threads waiting on the start condition
+ // in the decode routine so as to break them
+ ps_dec_thd->ai4_process_start = 1;
+ ps_dec_state_multi_core->i4_break_threads = 1;
+
+ ret = ithread_cond_signal(ps_dec_thd->pv_proc_start_condition);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret) return(IV_FAIL);
+
+ ret = ithread_mutex_unlock(ps_dec_thd->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret) return(IV_FAIL);
+
+ ithread_join(ps_dec_thd->pv_codec_thread_handle, NULL);
+ ps_dec_state_multi_core->au4_thread_launched[i] = 0;
+ ps_dec_state_multi_core->i4_break_threads = 0;
+ }
+ }
+ }
+
+ return IV_SUCCESS;
+}
+
/*****************************************************************************/
/* */
/* Function Name : impeg2d_api_reset */
@@ -1014,6 +1051,7 @@
if(ps_dec_state_multi_core != NULL)
{
+ impeg2d_join_threads(ps_dec_state_multi_core);
impeg2_buf_mgr_reset(ps_dec_state->pv_pic_buf_mg);
/* Display buffer manager init behaves like a reset
* as it doesn't need to preserve picture buffer addresses
@@ -1639,6 +1677,7 @@
WORD32 i4_num_threads;
UWORD32 u4_share_disp_buf, u4_chroma_format;
UWORD32 u4_deinterlace;
+ WORD32 i4_threads_active;
ps_dec_init_ip = (impeg2d_init_ip_t *)ps_ip;
ps_dec_init_op = (impeg2d_init_op_t *)ps_op;
@@ -1670,6 +1709,15 @@
u4_deinterlace = 0;
}
+ if(ps_dec_init_ip->s_ivd_init_ip_t.u4_size > offsetof(impeg2d_init_ip_t, u4_keep_threads_active))
+ {
+ i4_threads_active = ps_dec_init_ip->u4_keep_threads_active;
+ }
+ else
+ {
+ i4_threads_active = 0;
+ }
+
if( (u4_chroma_format != IV_YUV_420P) &&
(u4_chroma_format != IV_YUV_420SP_UV) &&
(u4_chroma_format != IV_YUV_420SP_VU))
@@ -1726,69 +1774,67 @@
for(i4_num_threads = 0; i4_num_threads < MAX_THREADS; i4_num_threads++)
{
-#ifdef KEEP_THREADS_ACTIVE
- WORD32 ret;
- UWORD8 *pv_buf;
- WORD32 mutex_size = ithread_get_mutex_lock_size();
- WORD32 cond_size = ithread_get_cond_struct_size();
-#endif
- /*************************************************************************/
- /* For MPEG2 Decoder Context */
- /*************************************************************************/
- ps_dec_state = ps_mem_rec->pv_base;
+ WORD32 ret;
+ UWORD8 *pv_buf;
+ WORD32 mutex_size = ithread_get_mutex_lock_size();
+ WORD32 cond_size = ithread_get_cond_struct_size();
+ /*************************************************************************/
+ /* For MPEG2 Decoder Context */
+ /*************************************************************************/
+ ps_dec_state = ps_mem_rec->pv_base;
- ps_dec_state_multi_core->ps_dec_state[i4_num_threads] = ps_dec_state;
+ ps_dec_state_multi_core->ps_dec_state[i4_num_threads] = ps_dec_state;
- ps_dec_state->ps_dec_state_multi_core = ps_dec_state_multi_core;
+ ps_dec_state->ps_dec_state_multi_core = ps_dec_state_multi_core;
- ps_dec_state->i4_num_cores = 1;
- /* @ */ /* Used for storing MemRecords */
- u4_num_mem_rec++;
- ps_mem_rec++;
+ ps_dec_state->i4_num_cores = 1;
+ /* @ */ /* Used for storing MemRecords */
+ u4_num_mem_rec++;
+ ps_mem_rec++;
- /* Thread handle */
- ps_dec_state->pv_codec_thread_handle = ps_mem_rec->pv_base;
- u4_num_mem_rec++;
- ps_mem_rec++;
+ /* Thread handle */
+ ps_dec_state->pv_codec_thread_handle = ps_mem_rec->pv_base;
+ u4_num_mem_rec++;
+ ps_mem_rec++;
-#ifdef KEEP_THREADS_ACTIVE
- pv_buf = ps_mem_rec->pv_base;
- if (ps_mem_rec->u4_mem_size < 2 * mutex_size)
- {
- ps_dec_init_op->s_ivd_init_op_t.u4_error_code = IMPEG2D_INIT_DEC_PER_MEM_INSUFFICIENT;
- return(IV_FAIL);
- }
+ pv_buf = ps_mem_rec->pv_base;
+ if (ps_mem_rec->u4_mem_size < 2 * mutex_size)
+ {
+ ps_dec_init_op->s_ivd_init_op_t.u4_error_code =
+ IMPEG2D_INIT_DEC_PER_MEM_INSUFFICIENT;
+ return(IV_FAIL);
+ }
- ps_dec_state->pv_proc_start_mutex = (UWORD8 *)pv_buf;
- ps_dec_state->pv_proc_done_mutex = (UWORD8 *)pv_buf + mutex_size;
+ ps_dec_state->pv_proc_start_mutex = (UWORD8 *)pv_buf;
+ ps_dec_state->pv_proc_done_mutex = (UWORD8 *)pv_buf + mutex_size;
- ret = ithread_mutex_init(ps_dec_state->pv_proc_start_mutex);
- RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
+ ret = ithread_mutex_init(ps_dec_state->pv_proc_start_mutex);
+ RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
- ret = ithread_mutex_init(ps_dec_state->pv_proc_done_mutex);
- RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
+ ret = ithread_mutex_init(ps_dec_state->pv_proc_done_mutex);
+ RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
- u4_num_mem_rec++;
- ps_mem_rec++;
+ u4_num_mem_rec++;
+ ps_mem_rec++;
- pv_buf = ps_mem_rec->pv_base;
- if (ps_mem_rec->u4_mem_size < 2 * cond_size)
- {
- ps_dec_init_op->s_ivd_init_op_t.u4_error_code = IMPEG2D_INIT_DEC_PER_MEM_INSUFFICIENT;
- return(IV_FAIL);
- }
- ps_dec_state->pv_proc_start_condition = (UWORD8 *)pv_buf;
- ps_dec_state->pv_proc_done_condition = (UWORD8 *)pv_buf + cond_size;
+ pv_buf = ps_mem_rec->pv_base;
+ if (ps_mem_rec->u4_mem_size < 2 * cond_size)
+ {
+ ps_dec_init_op->s_ivd_init_op_t.u4_error_code =
+ IMPEG2D_INIT_DEC_PER_MEM_INSUFFICIENT;
+ return(IV_FAIL);
+ }
+ ps_dec_state->pv_proc_start_condition = (UWORD8 *)pv_buf;
+ ps_dec_state->pv_proc_done_condition = (UWORD8 *)pv_buf + cond_size;
- ret = ithread_cond_init(ps_dec_state->pv_proc_start_condition);
- RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
+ ret = ithread_cond_init(ps_dec_state->pv_proc_start_condition);
+ RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
- ret = ithread_cond_init(ps_dec_state->pv_proc_done_condition);
- RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
+ ret = ithread_cond_init(ps_dec_state->pv_proc_done_condition);
+ RETURN_IF((ret != (IMPEG2D_ERROR_CODES_T)IV_SUCCESS), ret);
- u4_num_mem_rec++;
- ps_mem_rec++;
-#endif
+ u4_num_mem_rec++;
+ ps_mem_rec++;
/*************************************************************************/
/* For Motion Compensation Buffers */
@@ -1920,6 +1966,7 @@
ps_dec_state->u2_vertical_size = u4_max_frm_height;
ps_dec_state->u4_share_disp_buf = u4_share_disp_buf;
ps_dec_state->u4_deinterlace = u4_deinterlace;
+ ps_dec_state->i4_threads_active = i4_threads_active;
ps_dec_state->ps_deint_pic = NULL;
}
}
@@ -2085,10 +2132,8 @@
dec_state_multi_core_t *ps_dec_state_multi_core;
iv_mem_rec_t *ps_mem_rec;
iv_mem_rec_t *ps_temp_rec;
-#ifdef KEEP_THREADS_ACTIVE
IMPEG2D_ERROR_CODES_T ret;
dec_state_t *ps_dec_thd;
-#endif
@@ -2114,47 +2159,31 @@
ps_retr_mem_rec_op->s_ivd_retrieve_mem_rec_op_t.u4_error_code = IV_SUCCESS;
ps_retr_mem_rec_op->s_ivd_retrieve_mem_rec_op_t.u4_num_mem_rec_filled = ps_dec_state->u4_num_mem_records;
-#ifdef KEEP_THREADS_ACTIVE
- for(u4_i = 0; u4_i < MAX_THREADS; u4_i++)
+ if(ps_dec_state->i4_threads_active)
{
- ps_dec_thd = ps_dec_state_multi_core->ps_dec_state[u4_i];
- if(ps_dec_state_multi_core->au4_thread_launched[u4_i])
+ impeg2d_join_threads(ps_dec_state_multi_core);
+
+ for(u4_i = 0; u4_i < MAX_THREADS; u4_i++)
{
- ret = ithread_mutex_lock(ps_dec_thd->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret) return(IV_FAIL);
+ ps_dec_thd = ps_dec_state_multi_core->ps_dec_state[u4_i];
- // set process start for the threads waiting on the start condition
- // in the decode routine so as to break them
- ps_dec_thd->ai4_process_start = 1;
- ps_dec_state_multi_core->i4_break_threads = 1;
+ ret = ithread_cond_destroy(ps_dec_thd->pv_proc_start_condition);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
+ return(IV_FAIL);
- ret = ithread_cond_signal(ps_dec_thd->pv_proc_start_condition);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret) return(IV_FAIL);
+ ret = ithread_cond_destroy(ps_dec_thd->pv_proc_done_condition);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
+ return(IV_FAIL);
- ret = ithread_mutex_unlock(ps_dec_thd->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret) return(IV_FAIL);
+ ret = ithread_mutex_destroy(ps_dec_thd->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
+ return(IV_FAIL);
- ithread_join(ps_dec_thd->pv_codec_thread_handle, NULL);
- ps_dec_state_multi_core->au4_thread_launched[u4_i] = 0;
+ ret = ithread_mutex_destroy(ps_dec_thd->pv_proc_done_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
+ return(IV_FAIL);
}
-
- ret = ithread_cond_destroy(ps_dec_thd->pv_proc_start_condition);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
- return(IV_FAIL);
-
- ret = ithread_cond_destroy(ps_dec_thd->pv_proc_done_condition);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
- return(IV_FAIL);
-
- ret = ithread_mutex_destroy(ps_dec_thd->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
- return(IV_FAIL);
-
- ret = ithread_mutex_destroy(ps_dec_thd->pv_proc_done_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != ret)
- return(IV_FAIL);
}
-#endif
impeg2_jobq_deinit(ps_dec_state->pv_jobq);
IMPEG2D_PRINT_STATISTICS();
diff --git a/decoder/impeg2d_dec_hdr.c b/decoder/impeg2d_dec_hdr.c
index 26a043a..dc43e7d 100644
--- a/decoder/impeg2d_dec_hdr.c
+++ b/decoder/impeg2d_dec_hdr.c
@@ -945,34 +945,34 @@
UWORD32 u4_bits_read;
WORD32 i4_dequeue_job;
IMPEG2D_ERROR_CODES_T e_error;
-#ifdef KEEP_THREADS_ACTIVE
+
UWORD32 id = ps_dec->currThreadId;
dec_state_multi_core_t *ps_dec_state_multi_core = ps_dec->ps_dec_state_multi_core;
-#endif
while (1)
{
-#ifdef KEEP_THREADS_ACTIVE
- if(id != 0)
+ if(ps_dec->i4_threads_active)
{
- e_error = ithread_mutex_lock(ps_dec->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
- break;
-
- while(!ps_dec->ai4_process_start)
+ if(id != 0)
{
- ithread_cond_wait(ps_dec->pv_proc_start_condition,
- ps_dec->pv_proc_start_mutex);
+ e_error = ithread_mutex_lock(ps_dec->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
+ break;
+
+ while(!ps_dec->ai4_process_start)
+ {
+ ithread_cond_wait(ps_dec->pv_proc_start_condition,
+ ps_dec->pv_proc_start_mutex);
+ }
+ ps_dec->ai4_process_start = 0;
+ e_error = ithread_mutex_unlock(ps_dec->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
+ break;
+ // break off at the end of decoding all the frames
+ if(ps_dec_state_multi_core->i4_break_threads)
+ break;
}
- ps_dec->ai4_process_start = 0;
- e_error = ithread_mutex_unlock(ps_dec->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
- break;
- // break off at the end of decoding all the frames
- if(ps_dec_state_multi_core->i4_break_threads)
- break;
}
-#endif
i4_cur_row = ps_dec->u2_mb_y + 1;
i4_continue_decode = 1;
@@ -1041,12 +1041,8 @@
if ((IMPEG2D_ERROR_CODES_T)IVD_ERROR_NONE != e_error)
{
- impeg2d_next_start_code(ps_dec);
- if(ps_dec->s_bit_stream.u4_offset >= ps_dec->s_bit_stream.u4_max_offset)
- {
- ps_dec->u4_error_code = IMPEG2D_BITSTREAM_BUFF_EXCEEDED_ERR;
- return;
- }
+ ps_dec->u2_num_mbs_left = 0;
+ break;
}
/* Detecting next slice start code */
@@ -1155,27 +1151,30 @@
}
}
}
-#ifdef KEEP_THREADS_ACTIVE
- if(id != 0)
+ if(ps_dec->i4_threads_active)
{
- e_error = ithread_mutex_lock(ps_dec->pv_proc_done_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
- break;
+ if(id != 0)
+ {
+ e_error = ithread_mutex_lock(ps_dec->pv_proc_done_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
+ break;
- ps_dec->ai4_process_done = 1;
- ithread_cond_signal(ps_dec->pv_proc_done_condition);
+ ps_dec->ai4_process_done = 1;
+ ithread_cond_signal(ps_dec->pv_proc_done_condition);
- e_error = ithread_mutex_unlock(ps_dec->pv_proc_done_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
+ e_error = ithread_mutex_unlock(ps_dec->pv_proc_done_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != e_error)
+ break;
+ }
+ else
+ {
break;
+ }
}
else
{
break;
}
-#else
- break;
-#endif
}
}
@@ -1474,9 +1473,10 @@
ps_dec_state_multi_core = ps_dec->ps_dec_state_multi_core;
impeg2d_get_slice_pos(ps_dec_state_multi_core);
-#ifdef KEEP_THREADS_ACTIVE
- ps_dec->currThreadId = 0;
-#endif
+ if(ps_dec->i4_threads_active)
+ {
+ ps_dec->currThreadId = 0;
+ }
i4_min_mb_y = 1;
for(i=1; i < ps_dec->i4_num_cores; i++)
@@ -1494,29 +1494,32 @@
if(i4_status == 0 && !ps_dec_state_multi_core->au4_thread_launched[i])
{
-#ifdef KEEP_THREADS_ACTIVE
- ps_dec_thd->currThreadId = i;
-#endif
+ if(ps_dec->i4_threads_active)
+ {
+ ps_dec_thd->currThreadId = i;
+ }
ithread_create(ps_dec_thd->pv_codec_thread_handle, NULL, (void *)impeg2d_dec_pic_data_thread, ps_dec_thd);
ps_dec_state_multi_core->au4_thread_launched[i] = 1;
i4_min_mb_y = ps_dec_thd->u2_mb_y + 1;
}
-#ifndef KEEP_THREADS_ACTIVE
- else
+
+ else if (!ps_dec->i4_threads_active)
{
ps_dec_state_multi_core->au4_thread_launched[i] = 0;
break;
}
-#else
- i4_status = ithread_mutex_lock(ps_dec_thd->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
- ps_dec_thd->ai4_process_start = 1;
- ithread_cond_signal(ps_dec_thd->pv_proc_start_condition);
+ if(ps_dec->i4_threads_active)
+ {
+ i4_status = ithread_mutex_lock(ps_dec_thd->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
- i4_status = ithread_mutex_unlock(ps_dec_thd->pv_proc_start_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
-#endif
+ ps_dec_thd->ai4_process_start = 1;
+ ithread_cond_signal(ps_dec_thd->pv_proc_start_condition);
+
+ i4_status = ithread_mutex_unlock(ps_dec_thd->pv_proc_start_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
+ }
}
impeg2d_dec_pic_data_thread(ps_dec);
@@ -1527,22 +1530,25 @@
if(ps_dec_state_multi_core->au4_thread_launched[i])
{
ps_dec_thd = ps_dec_state_multi_core->ps_dec_state[i];
-#ifdef KEEP_THREADS_ACTIVE
- i4_status = ithread_mutex_lock(ps_dec_thd->pv_proc_done_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
-
- while(!ps_dec_thd->ai4_process_done)
+ if (ps_dec->i4_threads_active)
{
- ithread_cond_wait(ps_dec_thd->pv_proc_done_condition,
- ps_dec_thd->pv_proc_done_mutex);
+ i4_status = ithread_mutex_lock(ps_dec_thd->pv_proc_done_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
+
+ while(!ps_dec_thd->ai4_process_done)
+ {
+ ithread_cond_wait(ps_dec_thd->pv_proc_done_condition,
+ ps_dec_thd->pv_proc_done_mutex);
+ }
+ ps_dec_thd->ai4_process_done = 0;
+ i4_status = ithread_mutex_unlock(ps_dec_thd->pv_proc_done_mutex);
+ if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
}
- ps_dec_thd->ai4_process_done = 0;
- i4_status = ithread_mutex_unlock(ps_dec_thd->pv_proc_done_mutex);
- if((IMPEG2D_ERROR_CODES_T)IV_SUCCESS != i4_status) return;
-#else
- ithread_join(ps_dec_thd->pv_codec_thread_handle, NULL);
- ps_dec_state_multi_core->au4_thread_launched[i] = 0;
-#endif
+ else
+ {
+ ithread_join(ps_dec_thd->pv_codec_thread_handle, NULL);
+ ps_dec_state_multi_core->au4_thread_launched[i] = 0;
+ }
}
}
@@ -1598,7 +1604,8 @@
ps_stream = &ps_dec->s_bit_stream;
u4_start_code = impeg2d_bit_stream_nxt(ps_stream,START_CODE_LEN);
- while(u4_start_code == USER_DATA_START_CODE)
+ while((u4_start_code == USER_DATA_START_CODE) &&
+ (ps_stream->u4_offset <= ps_stream->u4_max_offset))
{
impeg2d_bit_stream_flush(ps_stream,START_CODE_LEN);
while((impeg2d_bit_stream_nxt(ps_stream,START_CODE_PREFIX_LEN) != START_CODE_PREFIX) &&
diff --git a/decoder/impeg2d_structs.h b/decoder/impeg2d_structs.h
index d108203..38a370f 100644
--- a/decoder/impeg2d_structs.h
+++ b/decoder/impeg2d_structs.h
@@ -316,7 +316,6 @@
void *pv_codec_thread_handle;
void *ps_dec_state_multi_core;
-#ifdef KEEP_THREADS_ACTIVE
UWORD32 currThreadId;
/**
* Condition variable to signal process start
@@ -347,7 +346,6 @@
* Process state end- One for each thread
*/
WORD32 ai4_process_done;
-#endif
UWORD32 u4_inp_ts;
pic_buf_t *ps_cur_pic;
pic_buf_t *ps_disp_pic;
@@ -423,6 +421,9 @@
/** Flag to indicate if Seq Display Extn is present */
UWORD8 u1_seq_disp_extn_present;
+
+ /** Keeps thread active*/
+ UWORD8 i4_threads_active;
}dec_state_t;
@@ -455,12 +456,10 @@
// and start decoding
UWORD32 au4_row_offset[MAX_MB_ROWS];
volatile UWORD32 u4_row_offset_cnt;
-#ifdef KEEP_THREADS_ACTIVE
/**
* Flag to signal processing thread to exit
*/
WORD32 i4_break_threads;
-#endif
}dec_state_multi_core_t;
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
index c741eab..d2e8795 100644
--- a/fuzzer/Android.bp
+++ b/fuzzer/Android.bp
@@ -27,5 +27,14 @@
"android-media-fuzzing-reports@google.com",
],
componentid: 155276,
+ hotlists: [
+ "4593311",
+ "2281331",
+ ],
+ description: "The fuzzer targets the APIs of libmpeg2dec",
+ vector: "remote",
+ service_privilege: "constrained",
+ users: "multi_user",
+ fuzzed_code_usage: "shipped",
},
}
diff --git a/fuzzer/mpeg2_dec_fuzzer.cpp b/fuzzer/mpeg2_dec_fuzzer.cpp
index 1492c02..a3a0d86 100644
--- a/fuzzer/mpeg2_dec_fuzzer.cpp
+++ b/fuzzer/mpeg2_dec_fuzzer.cpp
@@ -84,6 +84,7 @@
uint32_t mWidth;
uint32_t mHeight;
uint32_t mDeinterlace;
+ uint32_t mKeepThreadsActive;
iv_mem_rec_t *mMemRecords;
};
@@ -94,6 +95,7 @@
mWidth = 0;
mHeight = 0;
mDeinterlace = 1;
+ mKeepThreadsActive = 1;
memset(&mOutBufHandle, 0, sizeof(mOutBufHandle));
}
@@ -134,6 +136,7 @@
fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_max_frm_ht = MAX_FRAME_HEIGHT;
fill_mem_ip.u4_share_disp_buf = 0;
fill_mem_ip.u4_deinterlace = mDeinterlace;
+ fill_mem_ip.u4_keep_threads_active = mKeepThreadsActive;
fill_mem_ip.e_output_format = mColorFormat;
fill_mem_ip.s_ivd_fill_mem_rec_ip_t.u4_size =
@@ -180,6 +183,7 @@
init_ip.u4_share_disp_buf = 0;
init_ip.u4_deinterlace = mDeinterlace;
+ init_ip.u4_keep_threads_active = mKeepThreadsActive;
init_ip.s_ivd_init_ip_t.u4_num_mem_rec = numMemRecords;
init_ip.s_ivd_init_ip_t.e_output_format = mColorFormat;
init_ip.s_ivd_init_ip_t.u4_size = sizeof(impeg2d_init_ip_t);
@@ -331,7 +335,9 @@
void Codec::decodeHeader(const uint8_t *data, size_t size) {
setParams(IVD_DECODE_HEADER);
- while (size > 0) {
+ size_t numDecodeCalls = 0;
+
+ while (size > 0 && numDecodeCalls < kMaxNumDecodeCalls) {
IV_API_CALL_STATUS_T ret;
ivd_video_decode_ip_t dec_ip;
ivd_video_decode_op_t dec_op;
@@ -358,6 +364,7 @@
data += bytes_consumed;
size -= bytes_consumed;
+ numDecodeCalls++;
mWidth = std::min(dec_op.u4_pic_wd, (UWORD32)10240);
mHeight = std::min(dec_op.u4_pic_ht, (UWORD32)10240);
diff --git a/fuzzer/ossfuzz.sh b/fuzzer/ossfuzz.sh
index 3493031..c3497c6 100755
--- a/fuzzer/ossfuzz.sh
+++ b/fuzzer/ossfuzz.sh
@@ -18,6 +18,12 @@
test "${WORK}" != "" || exit 1
test "${OUT}" != "" || exit 1
+#Opt out of shift sanitizers in undefined sanitizer
+if [[ $SANITIZER = *undefined* ]]; then
+ CFLAGS="$CFLAGS -fno-sanitize=shift"
+ CXXFLAGS="$CXXFLAGS -fno-sanitize=shift"
+fi
+
# Build libmpeg2
build_dir=$WORK/build
rm -rf ${build_dir}
@@ -25,20 +31,9 @@
pushd ${build_dir}
cmake $SRC/libmpeg2
-make -j$(nproc)
+make -j$(nproc) mpeg2_dec_fuzzer
+cp ${build_dir}/mpeg2_dec_fuzzer $OUT/
popd
-# build fuzzers
-$CXX $CXXFLAGS -std=c++11 \
--I$SRC/libmpeg2 \
--I$SRC/libmpeg2/common \
--I$SRC/libmpeg2/decoder \
--I${build_dir} \
--Wl,--start-group \
-$LIB_FUZZING_ENGINE \
-$SRC/libmpeg2/fuzzer/mpeg2_dec_fuzzer.cpp -o $OUT/mpeg2_dec_fuzzer \
-${build_dir}/libmpeg2dec.a \
--Wl,--end-group
-
cp $SRC/mpeg2_dec_fuzzer_seed_corpus.zip $OUT/mpeg2_dec_fuzzer_seed_corpus.zip
cp $SRC/libmpeg2/fuzzer/mpeg2_dec_fuzzer.dict $OUT/mpeg2_dec_fuzzer.dict
diff --git a/test/decoder/main.c b/test/decoder/main.c
index 51f2c44..2bd0c22 100644
--- a/test/decoder/main.c
+++ b/test/decoder/main.c
@@ -219,6 +219,9 @@
WORD32 quit;
WORD32 paused;
+ /* Keep threads active*/
+ WORD32 i4_keep_threads_active;
+
void *pv_disp_ctx;
void *display_thread_handle;
@@ -270,6 +273,7 @@
SOC,
PICLEN,
PICLEN_FILE,
+ KEEP_THREADS_ACTIVE,
}ARGUMENT_T;
typedef struct
@@ -331,6 +335,8 @@
"Set Architecture. Supported values ARM_NONEON, ARM_A9Q, ARM_A7, ARM_A5, ARM_NEONINTR, X86_GENERIC, X86_SSSE3, X86_SSE4 \n" },
{ "--", "--soc", SOC,
"Set SOC. Supported values GENERIC, HISI_37X \n" },
+ { "--", "--keep_threads_active", KEEP_THREADS_ACTIVE,
+ "keep threads active" },
#if 0
{ "--", "--degrade_type", DEGRADE_TYPE,
@@ -860,6 +866,7 @@
/*****************************************************************************/
void codec_exit(CHAR *pc_err_message)
{
+ printf("Summary\n");
printf("%s\n", pc_err_message);
exit(-1);
}
@@ -1322,6 +1329,10 @@
sscanf(value, "%s", ps_app_ctx->ac_piclen_fname);
break;
+ case KEEP_THREADS_ACTIVE:
+ sscanf(value, "%d", &ps_app_ctx->i4_keep_threads_active);
+ break;
+
case INVALID:
default:
printf("Ignoring argument : %s\n", argument);
@@ -1879,6 +1890,8 @@
s_app_ctx.get_color_fmt = &default_get_color_fmt;
+ s_app_ctx.i4_keep_threads_active = 1;
+
/* Set function pointers for display */
#ifdef SDL_DISPLAY
s_app_ctx.disp_init = &sdl_disp_init;
@@ -2130,6 +2143,7 @@
(s_app_ctx.max_ht == 0) ? MAX_FRAME_HEIGHT : s_app_ctx.max_ht;
s_fill_mem_rec_ip.u4_share_disp_buf = s_app_ctx.share_disp_buf;
s_fill_mem_rec_ip.u4_deinterlace = s_app_ctx.deinterlace;
+ s_fill_mem_rec_ip.u4_keep_threads_active = s_app_ctx.i4_keep_threads_active;
s_fill_mem_rec_ip.e_output_format =
(IV_COLOR_FORMAT_T)s_app_ctx.e_output_chroma_format;
@@ -2196,6 +2210,7 @@
s_init_ip.u4_share_disp_buf = s_app_ctx.share_disp_buf;
s_init_ip.u4_deinterlace = s_app_ctx.deinterlace;
+ s_init_ip.u4_keep_threads_active = s_app_ctx.i4_keep_threads_active;
s_init_ip.s_ivd_init_ip_t.u4_num_mem_rec = u4_num_mem_recs;
s_init_ip.s_ivd_init_ip_t.e_output_format =
(IV_COLOR_FORMAT_T)s_app_ctx.e_output_chroma_format;