[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;