DO NOT MERGE - Mark RQ1A.201004.001 as merged

Bug: 172690556
Change-Id: Ic4a1c08122d6034e61c5f5a552e8be164a243a8e
diff --git a/Android.bp b/Android.bp
index 0e705cc..c60d9e1 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,6 +15,8 @@
         // common/x86/ihevc_sao_ssse3_intr.c: implicit conversion from
         // 'int' to 'char' changes value from 128 to -128
         "-Wno-error=constant-conversion",
+        // #KEEP_THREAD_ACTIVE is experimental
+        "-UKEEP_THREADS_ACTIVE",
     ],
 
     export_include_dirs: [
@@ -277,30 +279,6 @@
             },
         },
 
-        mips64: {
-            local_include_dirs: [
-                "decoder/mips",
-                "common/mips",
-            ],
-
-            srcs: [
-                "decoder/mips/ihevcd_function_selector.c",
-                "decoder/mips/ihevcd_function_selector_mips_generic.c",
-            ],
-        },
-
-        mips: {
-            local_include_dirs: [
-                "decoder/mips",
-                "common/mips",
-            ],
-
-            srcs: [
-                "decoder/mips/ihevcd_function_selector.c",
-                "decoder/mips/ihevcd_function_selector_mips_generic.c",
-            ],
-        },
-
         x86_64: {
             cflags: [
                 "-DX86",
@@ -395,7 +373,7 @@
         misc_undefined: ["bounds"],
         // Enable CFI if this becomes a shared library.
         // cfi: true,
-        blacklist: "libhevc_blacklist.txt",
+        blocklist: "libhevc_blocklist.txt",
     },
 
     apex_available: [
@@ -416,6 +394,7 @@
         "-Wall",
         "-Werror",
     ],
+    gtest: false,
     srcs: ["test/decoder/main.c"],
     static_libs: ["libhevcdec"],
     target: {
@@ -775,7 +754,7 @@
         misc_undefined: ["bounds"],
         // Enable CFI if this becomes a shared library.
         // cfi: true,
-        blacklist: "libhevc_blacklist.txt",
+        blocklist: "libhevc_blocklist.txt",
     },
 
     apex_available: [
@@ -794,6 +773,7 @@
         "-Wall",
         "-Werror",
     ],
+    gtest: false,
     srcs: ["test/encoder/main.c"],
     static_libs: ["libhevcenc"],
     sanitize: {
diff --git a/METADATA b/METADATA
new file mode 100644
index 0000000..d97975c
--- /dev/null
+++ b/METADATA
@@ -0,0 +1,3 @@
+third_party {
+  license_type: NOTICE
+}
diff --git a/OWNERS b/OWNERS
index 4516783..819c45f 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,2 +1,4 @@
+# owners for external/libhevc
+include platform/frameworks/av:/media/janitors/OWNERS-codecs
 marcone@google.com
 essick@google.com
diff --git a/common/arm/ihevc_intra_pred_filters_neon_intr.c b/common/arm/ihevc_intra_pred_filters_neon_intr.c
index 2564ffa..190cccc 100644
--- a/common/arm/ihevc_intra_pred_filters_neon_intr.c
+++ b/common/arm/ihevc_intra_pred_filters_neon_intr.c
@@ -61,14 +61,6 @@
 #define T32_4NT 128
 #define T16_4NT 64
 
-
-
-/*****************************************************************************/
-/* Table Look-up                                                             */
-/*****************************************************************************/
-
-#define GET_BITS(y,x) ((y) & (1 << x)) && (1 << x)
-
 /*****************************************************************************/
 /* Function Definition                                                      */
 /*****************************************************************************/
@@ -338,7 +330,7 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T16_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, 8);
+                    get_bits = GET_BIT(nbr_flags_temp, 8);
 
                     /* only pel substitution for TL */
                     if(!get_bits)
@@ -346,7 +338,7 @@
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags_temp, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
@@ -398,14 +390,14 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T32_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags, 16);
+                    get_bits = GET_BIT(nbr_flags, 16);
                     /* only pel substitution for TL */
                     if(!get_bits)
                         pu1_dst[nbr_id_from_bl] = pu1_dst[nbr_id_from_bl - 1];
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
diff --git a/common/arm/ihevc_intra_ref_substitution_a9q.c b/common/arm/ihevc_intra_ref_substitution_a9q.c
index d090d84..fcdf0f2 100644
--- a/common/arm/ihevc_intra_ref_substitution_a9q.c
+++ b/common/arm/ihevc_intra_ref_substitution_a9q.c
@@ -56,12 +56,7 @@
 #define T16_4NT 64
 #define T16C_4NT 64
 #define T8C_4NT 32
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
 
-#define GET_BIT(y,x) ((y) & (1 << x)) && (1 << x)
-#define GET_BITS(y,x) ((y) & (1 << x)) && (1 << x)
 /**
 *******************************************************************************
 *
@@ -652,7 +647,7 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T16_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, 8);
+                    get_bits = GET_BIT(nbr_flags_temp, 8);
 
                     /* only pel substitution for TL */
                     if(!get_bits)
@@ -660,7 +655,7 @@
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags_temp, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
@@ -791,14 +786,14 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T32_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags, 16);
+                    get_bits = GET_BIT(nbr_flags, 16);
                     /* only pel substitution for TL */
                     if(!get_bits)
                         pu1_dst[nbr_id_from_bl] = pu1_dst[nbr_id_from_bl - 1];
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
diff --git a/common/ihevc_chroma_intra_pred_filters.c b/common/ihevc_chroma_intra_pred_filters.c
index 8b3c992..fe14d8a 100644
--- a/common/ihevc_chroma_intra_pred_filters.c
+++ b/common/ihevc_chroma_intra_pred_filters.c
@@ -81,16 +81,6 @@
 #define T16_4NT 64
 #define T16C_4NT 64
 #define T8C_4NT 32
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
-
-#define GET_BIT(y,x) ((y) & (1 << x)) && (1 << x)
-
-
-/*****************************************************************************/
-/* Function Definition                                                      */
-/*****************************************************************************/
 
 /**
 *******************************************************************************
diff --git a/common/ihevc_intra_pred.h b/common/ihevc_intra_pred.h
index a29e99d..c2902ea 100644
--- a/common/ihevc_intra_pred.h
+++ b/common/ihevc_intra_pred.h
@@ -42,6 +42,8 @@
 /*****************************************************************************/
 #define look_up_trailing_zeros(x) (0 == (x) ? 8 : CTZ(x))
 
+#define GET_BIT(y,x) ((y) & (1 << (x)))
+
 /*****************************************************************************/
 /* Function Declarations                                                     */
 /*****************************************************************************/
diff --git a/common/ihevc_intra_pred_filters.c b/common/ihevc_intra_pred_filters.c
index abb219a..41e4a1f 100644
--- a/common/ihevc_intra_pred_filters.c
+++ b/common/ihevc_intra_pred_filters.c
@@ -70,21 +70,6 @@
 #define T32_4NT 128
 #define T16_4NT 64
 
-
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
-#define GET_BITS(y,x) ((y) & (1 << x)) && (1 << x)
-
-/*****************************************************************************/
-/* global tables Definition                                                  */
-/*****************************************************************************/
-
-
-/*****************************************************************************/
-/* Function Definition                                                      */
-/*****************************************************************************/
-
 /**
 *******************************************************************************
 *
@@ -454,7 +439,7 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T16_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, 8);
+                    get_bits = GET_BIT(nbr_flags_temp, 8);
 
                     /* only pel substitution for TL */
                     if(!get_bits)
@@ -462,7 +447,7 @@
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags_temp, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
@@ -594,14 +579,14 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T32_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags, 16);
+                    get_bits = GET_BIT(nbr_flags, 16);
                     /* only pel substitution for TL */
                     if(!get_bits)
                         pu1_dst[nbr_id_from_bl] = pu1_dst[nbr_id_from_bl - 1];
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
diff --git a/common/ithread.c b/common/ithread.c
index 0b55206..2e19439 100644
--- a/common/ithread.c
+++ b/common/ithread.c
@@ -181,3 +181,28 @@
 
     return core_id;
 }
+
+WORD32 ithread_get_cond_struct_size(void)
+{
+    return (sizeof(pthread_cond_t));
+}
+
+WORD32 ithread_cond_init(void *cond)
+{
+    return pthread_cond_init((pthread_cond_t *)cond, NULL);
+}
+
+WORD32 ithread_cond_destroy(void *cond)
+{
+    return pthread_cond_destroy((pthread_cond_t *)cond);
+}
+
+WORD32 ithread_cond_wait(void *cond, void *mutex)
+{
+    return pthread_cond_wait((pthread_cond_t *)cond, (pthread_mutex_t *)mutex);
+}
+
+WORD32 ithread_cond_signal(void *cond)
+{
+    return pthread_cond_signal((pthread_cond_t *)cond);
+}
diff --git a/common/ithread.h b/common/ithread.h
index f435e78..e919586 100644
--- a/common/ithread.h
+++ b/common/ithread.h
@@ -75,4 +75,14 @@
 WORD32  ithread_sem_destroy(void *sem);
 
 WORD32 ithread_set_affinity(WORD32 core_id);
+
+WORD32 ithread_get_cond_struct_size(void);
+
+WORD32 ithread_cond_init(void *cond);
+
+WORD32 ithread_cond_destroy(void *cond);
+
+WORD32 ithread_cond_wait(void *cond, void *mutex);
+
+WORD32 ithread_cond_signal(void *cond);
 #endif /* __ITHREAD_H__ */
diff --git a/common/x86/ihevc_chroma_intra_pred_filters_sse42_intr.c b/common/x86/ihevc_chroma_intra_pred_filters_sse42_intr.c
index 1de4253..3ae02f2 100644
--- a/common/x86/ihevc_chroma_intra_pred_filters_sse42_intr.c
+++ b/common/x86/ihevc_chroma_intra_pred_filters_sse42_intr.c
@@ -68,19 +68,6 @@
 #define T16_4NT 64
 #define T16C_4NT 64
 #define T8C_4NT 32
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
-
-#define GET_BIT(y,x) ((y) & (1 << x)) && (1 << x)
-
-/* tables to shuffle 8-bit values */
-
-/*****************************************************************************/
-/* Function Definition                                                      */
-/*****************************************************************************/
-
-
 
 /**
 *******************************************************************************
diff --git a/common/x86/ihevc_chroma_intra_pred_filters_ssse3_intr.c b/common/x86/ihevc_chroma_intra_pred_filters_ssse3_intr.c
index 6a3883e..b3f8c1e 100644
--- a/common/x86/ihevc_chroma_intra_pred_filters_ssse3_intr.c
+++ b/common/x86/ihevc_chroma_intra_pred_filters_ssse3_intr.c
@@ -87,19 +87,6 @@
 #define T16_4NT 64
 #define T16C_4NT 64
 #define T8C_4NT 32
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
-
-#define GET_BIT(y,x) ((y) & (1 << x)) && (1 << x)
-
-/* tables to shuffle 8-bit values */
-
-/*****************************************************************************/
-/* Function Definition                                                      */
-/*****************************************************************************/
-
-
 
 /**
 *******************************************************************************
diff --git a/common/x86/ihevc_intra_pred_filters_sse42_intr.c b/common/x86/ihevc_intra_pred_filters_sse42_intr.c
index e72f042..0a1ce0a 100644
--- a/common/x86/ihevc_intra_pred_filters_sse42_intr.c
+++ b/common/x86/ihevc_intra_pred_filters_sse42_intr.c
@@ -68,24 +68,6 @@
 #define T32_4NT 128
 #define T16_4NT 64
 
-
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
-#define GET_BITS(y,x) ((y) & (1 << x)) && (1 << x)
-
-/* tables to shuffle 8-bit values */
-
-/*****************************************************************************/
-/* global tables Definition                                                  */
-/*****************************************************************************/
-
-
-
-/*****************************************************************************/
-/* Function Definition                                                      */
-/*****************************************************************************/
-
 /**
 *******************************************************************************
 *
diff --git a/common/x86/ihevc_intra_pred_filters_ssse3_intr.c b/common/x86/ihevc_intra_pred_filters_ssse3_intr.c
index ea35672..8441a8a 100644
--- a/common/x86/ihevc_intra_pred_filters_ssse3_intr.c
+++ b/common/x86/ihevc_intra_pred_filters_ssse3_intr.c
@@ -71,25 +71,6 @@
 #define T32_4NT 128
 #define T16_4NT 64
 
-
-/****************************************************************************/
-/* Function Macros                                                          */
-/****************************************************************************/
-#define GET_BITS(y,x) ((y) & (1 << x)) && (1 << x)
-
-/* tables to shuffle 8-bit values */
-
-
-/*****************************************************************************/
-/* global tables Definition                                                  */
-/*****************************************************************************/
-
-
-/*****************************************************************************/
-/* Function Definition                                                      */
-/*****************************************************************************/
-
-
 /**
 *******************************************************************************
 *
@@ -287,7 +268,7 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T16_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, 8);
+                    get_bits = GET_BIT(nbr_flags_temp, 8);
 
                     /* only pel substitution for TL */
                     if(!get_bits)
@@ -295,7 +276,7 @@
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags_temp, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags_temp, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
@@ -349,14 +330,14 @@
                 /* The Top-left flag is at the last bit location of nbr_flags*/
                 if(nbr_id_from_bl == (T32_4NT / 2))
                 {
-                    get_bits = GET_BITS(nbr_flags, 16);
+                    get_bits = GET_BIT(nbr_flags, 16);
                     /* only pel substitution for TL */
                     if(!get_bits)
                         pu1_dst[nbr_id_from_bl] = pu1_dst[nbr_id_from_bl - 1];
                 }
                 else
                 {
-                    get_bits = GET_BITS(nbr_flags, frwd_nbr_flag);
+                    get_bits = GET_BIT(nbr_flags, frwd_nbr_flag);
                     if(!get_bits)
                     {
                         /* 8 pel substitution (other than TL) */
diff --git a/decoder/ihevcd_api.c b/decoder/ihevcd_api.c
index 134ed31..4d094be 100644
--- a/decoder/ihevcd_api.c
+++ b/decoder/ihevcd_api.c
@@ -1215,6 +1215,52 @@
                         (UWORD8 *)pv_buf + (i * handle_size);
     }
 
+#ifdef KEEP_THREADS_ACTIVE
+    /* Request memory to hold mutex (start/done) for each processing thread */
+    size = 2 * MAX_PROCESS_THREADS * ithread_get_mutex_lock_size();
+    pv_buf = ps_codec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
+    RETURN_IF((NULL == pv_buf), IV_FAIL);
+    memset(pv_buf, 0, size);
+
+    for(i = 0; i < MAX_PROCESS_THREADS; i++)
+    {
+        WORD32 ret;
+        WORD32 mutex_size = ithread_get_mutex_lock_size();
+        ps_codec->apv_proc_start_mutex[i] =
+                        (UWORD8 *)pv_buf + (2 * i * mutex_size);
+        ps_codec->apv_proc_done_mutex[i] =
+                        (UWORD8 *)pv_buf + ((2 * i + 1) * mutex_size);
+
+        ret = ithread_mutex_init(ps_codec->apv_proc_start_mutex[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+        ret = ithread_mutex_init(ps_codec->apv_proc_done_mutex[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+    }
+
+    size = 2 * MAX_PROCESS_THREADS * ithread_get_cond_struct_size();
+    pv_buf = ps_codec->pf_aligned_alloc(pv_mem_ctxt, 128, size);
+    RETURN_IF((NULL == pv_buf), IV_FAIL);
+    memset(pv_buf, 0, size);
+
+    for(i = 0; i < MAX_PROCESS_THREADS; i++)
+    {
+        WORD32 ret;
+        WORD32 cond_size = ithread_get_cond_struct_size();
+        ps_codec->apv_proc_start_condition[i] =
+                        (UWORD8 *)pv_buf + (2 * i * cond_size);
+        ps_codec->apv_proc_done_condition[i] =
+                        (UWORD8 *)pv_buf + ((2 * i + 1) * cond_size);
+
+        ret = ithread_cond_init(ps_codec->apv_proc_start_condition[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+        ret = ithread_cond_init(ps_codec->apv_proc_done_condition[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+    }
+
+#endif
+
     /* Request memory for static bitstream buffer which holds bitstream after emulation prevention */
     size = MIN_BITSBUF_SIZE;
     pv_buf = pf_aligned_alloc(pv_mem_ctxt, 128, size + 16); //Alloc extra for parse optimization
@@ -1433,6 +1479,43 @@
     pf_aligned_free = ps_codec->pf_aligned_free;
     pv_mem_ctxt = ps_codec->pv_mem_ctxt;
 
+#ifdef KEEP_THREADS_ACTIVE
+    /* Wait for threads */
+    ps_codec->i4_break_threads = 1;
+    for(int i = 0; i < MAX_PROCESS_THREADS; i++)
+    {
+        WORD32 ret;
+        if(ps_codec->ai4_process_thread_created[i])
+        {
+            ret = ithread_mutex_lock(ps_codec->apv_proc_start_mutex[i]);
+            RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+            ps_codec->ai4_process_start[i] = 1;
+            ret = ithread_cond_signal(ps_codec->apv_proc_start_condition[i]);
+            RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+            ret = ithread_mutex_unlock(ps_codec->apv_proc_start_mutex[i]);
+            RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+            ithread_join(ps_codec->apv_process_thread_handle[i], NULL);
+
+            ps_codec->ai4_process_thread_created[i] = 0;
+        }
+        ret = ithread_cond_destroy(ps_codec->apv_proc_start_condition[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+        ret = ithread_cond_destroy(ps_codec->apv_proc_done_condition[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+        ret = ithread_mutex_destroy(ps_codec->apv_proc_start_mutex[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+        ret = ithread_mutex_destroy(ps_codec->apv_proc_done_mutex[i]);
+        RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+    }
+    ALIGNED_FREE(ps_codec, ps_codec->apv_proc_start_mutex[0]);
+    ALIGNED_FREE(ps_codec, ps_codec->apv_proc_start_condition[0]);
+#endif
 
     ALIGNED_FREE(ps_codec, ps_codec->apv_process_thread_handle[0]);
     ALIGNED_FREE(ps_codec, ps_codec->pu1_bitsbuf_static);
diff --git a/decoder/ihevcd_decode.c b/decoder/ihevcd_decode.c
index 9f634b7..1eabb3b 100644
--- a/decoder/ihevcd_decode.c
+++ b/decoder/ihevcd_decode.c
@@ -907,8 +907,22 @@
         {
             if(ps_codec->ai4_process_thread_created[i])
             {
+#ifdef KEEP_THREADS_ACTIVE
+                ret = ithread_mutex_lock(ps_codec->apv_proc_done_mutex[i]);
+                RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+                while(!ps_codec->ai4_process_done[i])
+                {
+                    ithread_cond_wait(ps_codec->apv_proc_done_condition[i],
+                                      ps_codec->apv_proc_done_mutex[i]);
+                }
+                ps_codec->ai4_process_done[i] = 0;
+                ret = ithread_mutex_unlock(ps_codec->apv_proc_done_mutex[i]);
+                RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+#else
                 ithread_join(ps_codec->apv_process_thread_handle[i], NULL);
                 ps_codec->ai4_process_thread_created[i] = 0;
+#endif
             }
         }
 
diff --git a/decoder/ihevcd_process_slice.c b/decoder/ihevcd_process_slice.c
index c5af08e..50b2c00 100644
--- a/decoder/ihevcd_process_slice.c
+++ b/decoder/ihevcd_process_slice.c
@@ -1591,56 +1591,98 @@
 }
 void ihevcd_process_thread(process_ctxt_t *ps_proc)
 {
+    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
     {
         ithread_set_affinity(ps_proc->i4_id + 1);
     }
+
+#ifdef KEEP_THREADS_ACTIVE
     while(1)
     {
-        IHEVCD_ERROR_T ret;
-        proc_job_t s_job;
+        codec_t *ps_dec = ps_proc->ps_codec;
+        DEBUG("In ihevcd_process_thread \n");
 
-        ret = ihevcd_jobq_dequeue((jobq_t *)ps_proc->pv_proc_jobq, &s_job,
-                                  sizeof(proc_job_t), 1);
+        ret = ithread_mutex_lock(ps_dec->apv_proc_start_mutex[ps_proc->i4_id]);
         if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
             break;
 
-        ps_proc->i4_ctb_cnt = s_job.i2_ctb_cnt;
-        ps_proc->i4_ctb_x = s_job.i2_ctb_x;
-        ps_proc->i4_ctb_y = s_job.i2_ctb_y;
-        ps_proc->i4_cur_slice_idx = s_job.i2_slice_idx;
-
-
-
-        if(CMD_PROCESS == s_job.i4_cmd)
+        while(!ps_dec->ai4_process_start[ps_proc->i4_id])
         {
-            ihevcd_init_proc_ctxt(ps_proc, s_job.i4_tu_coeff_data_ofst);
-            ihevcd_process(ps_proc);
+            ithread_cond_wait(ps_dec->apv_proc_start_condition[ps_proc->i4_id],
+                              ps_dec->apv_proc_start_mutex[ps_proc->i4_id]);
         }
-        else if(CMD_FMTCONV == s_job.i4_cmd)
-        {
-            sps_t *ps_sps;
-            codec_t *ps_codec;
-            ivd_out_bufdesc_t *ps_out_buffer;
-            WORD32 num_rows;
+        ps_dec->ai4_process_start[ps_proc->i4_id] = 0;
+        ret = ithread_mutex_unlock(ps_dec->apv_proc_start_mutex[ps_proc->i4_id]);
+        if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
+            break;
 
-            if(0 == ps_proc->i4_init_done)
+        DEBUG(" Got control at ihevcd_process_thread \n");
+
+        if(ps_dec->i4_break_threads == 1)
+            break;
+#endif
+        while(1)
+        {
+            proc_job_t s_job;
+
+            ret = ihevcd_jobq_dequeue((jobq_t *)ps_proc->pv_proc_jobq, &s_job,
+                                    sizeof(proc_job_t), 1);
+            if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
+                break;
+
+            ps_proc->i4_ctb_cnt = s_job.i2_ctb_cnt;
+            ps_proc->i4_ctb_x = s_job.i2_ctb_x;
+            ps_proc->i4_ctb_y = s_job.i2_ctb_y;
+            ps_proc->i4_cur_slice_idx = s_job.i2_slice_idx;
+
+
+
+            if(CMD_PROCESS == s_job.i4_cmd)
             {
-                ihevcd_init_proc_ctxt(ps_proc, 0);
+                ihevcd_init_proc_ctxt(ps_proc, s_job.i4_tu_coeff_data_ofst);
+                ihevcd_process(ps_proc);
             }
-            ps_sps = ps_proc->ps_sps;
-            ps_codec = ps_proc->ps_codec;
-            ps_out_buffer = ps_proc->ps_out_buffer;
-            num_rows = 1 << ps_sps->i1_log2_ctb_size;
+            else if(CMD_FMTCONV == s_job.i4_cmd)
+            {
+                sps_t *ps_sps;
+                codec_t *ps_codec;
+                ivd_out_bufdesc_t *ps_out_buffer;
+                WORD32 num_rows;
 
-            num_rows = MIN(num_rows, (ps_codec->i4_disp_ht - (s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size)));
+                if(0 == ps_proc->i4_init_done)
+                {
+                    ihevcd_init_proc_ctxt(ps_proc, 0);
+                }
+                ps_sps = ps_proc->ps_sps;
+                ps_codec = ps_proc->ps_codec;
+                ps_out_buffer = ps_proc->ps_out_buffer;
+                num_rows = 1 << ps_sps->i1_log2_ctb_size;
 
-            if(num_rows < 0)
-                num_rows = 0;
+                num_rows = MIN(num_rows,
+                               (ps_codec->i4_disp_ht - (s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size))
+                              );
 
-            ihevcd_fmt_conv(ps_proc->ps_codec, ps_proc, ps_out_buffer->pu1_bufs[0], ps_out_buffer->pu1_bufs[1], ps_out_buffer->pu1_bufs[2],
-                            s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size, num_rows);
+                if(num_rows < 0)
+                    num_rows = 0;
+
+                ihevcd_fmt_conv(ps_proc->ps_codec, ps_proc, ps_out_buffer->pu1_bufs[0],
+                                ps_out_buffer->pu1_bufs[1], ps_out_buffer->pu1_bufs[2],
+                                s_job.i2_ctb_y << ps_sps->i1_log2_ctb_size, num_rows);
+            }
         }
+#ifdef KEEP_THREADS_ACTIVE
+        ret = ithread_mutex_lock(ps_dec->apv_proc_done_mutex[ps_proc->i4_id]);
+        if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
+            break;
+
+        ps_dec->ai4_process_done[ps_proc->i4_id] = 1;
+        ithread_cond_signal(ps_dec->apv_proc_done_condition[ps_proc->i4_id]);
+
+        ret = ithread_mutex_unlock(ps_dec->apv_proc_done_mutex[ps_proc->i4_id]);
+        if((IHEVCD_ERROR_T)IHEVCD_SUCCESS != ret)
+            break;
     }
+#endif
     //ithread_exit(0);
     return;
 }
diff --git a/decoder/ihevcd_structs.h b/decoder/ihevcd_structs.h
index 5b0837d..407818a 100644
--- a/decoder/ihevcd_structs.h
+++ b/decoder/ihevcd_structs.h
@@ -2039,6 +2039,43 @@
      */
     parse_ctxt_t s_parse;
 
+#ifdef KEEP_THREADS_ACTIVE
+    /**
+     * Condition variable to signal process start
+     */
+    void *apv_proc_start_condition[MAX_PROCESS_THREADS];
+
+    /**
+     * Mutex used to keep the functions thread-safe
+     */
+    void *apv_proc_start_mutex[MAX_PROCESS_THREADS];
+
+    /**
+     * Process state start- One for each thread
+     */
+    WORD32 ai4_process_start[MAX_PROCESS_THREADS];
+
+    /**
+     * Condition variable to signal process done
+     */
+    void *apv_proc_done_condition[MAX_PROCESS_THREADS];
+
+    /**
+     * Mutex used to keep the functions thread-safe
+     */
+    void *apv_proc_done_mutex[MAX_PROCESS_THREADS];
+
+    /**
+     * Process state end- One for each thread
+     */
+    WORD32 ai4_process_done[MAX_PROCESS_THREADS];
+
+    /**
+     * Flag to signal processing thread to exit
+     */
+    WORD32 i4_break_threads;
+#endif
+
     /**
      * Processing context - One for each processing thread
      */
diff --git a/decoder/ihevcd_utils.c b/decoder/ihevcd_utils.c
index fef3f74..b914a9b 100755
--- a/decoder/ihevcd_utils.c
+++ b/decoder/ihevcd_utils.c
@@ -1040,6 +1040,9 @@
     /* Reset the jobq to start of the jobq buffer */
     ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
 
+#ifdef KEEP_THREADS_ACTIVE
+    ps_codec->i4_break_threads = 0;
+#endif
     ps_codec->s_parse.i4_pic_pu_idx = 0;
     ps_codec->s_parse.i4_pic_tu_idx = 0;
 
@@ -1238,10 +1241,23 @@
             ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
             if(i < (ps_codec->i4_num_cores - 1))
             {
-                ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
-                               (void *)ihevcd_process_thread,
-                               (void *)&ps_codec->as_process[i]);
-                ps_codec->ai4_process_thread_created[i] = 1;
+                if (!ps_codec->ai4_process_thread_created[i])
+                {
+                    ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
+                                (void *)ihevcd_process_thread,
+                                (void *)&ps_codec->as_process[i]);
+                    ps_codec->ai4_process_thread_created[i] = 1;
+                }
+#ifdef KEEP_THREADS_ACTIVE
+                ret = ithread_mutex_lock(ps_codec->apv_proc_start_mutex[i]);
+                RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+
+                ps_codec->ai4_process_start[i] = 1;
+                ithread_cond_signal(ps_codec->apv_proc_start_condition[i]);
+
+                ret = ithread_mutex_unlock(ps_codec->apv_proc_start_mutex[i]);
+                RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
+#endif
             }
             else
             {
diff --git a/encoder/ihevce_defs.h b/encoder/ihevce_defs.h
index 5f60e3e..ffc35e3 100644
--- a/encoder/ihevce_defs.h
+++ b/encoder/ihevce_defs.h
@@ -469,6 +469,7 @@
 #define BELOW_REF_DEVIATION (0.0)
 #define ABOVE_REF_DEVIATION (220.0)
 
+#define MIN_BITRATE 4000
 #define MIN_QP_MOD_OFFSET -10
 #define MAX_QP_MOD_OFFSET 3
 #define TOT_QP_MOD_OFFSET (MAX_QP_MOD_OFFSET - MIN_QP_MOD_OFFSET + 1)
diff --git a/encoder/ihevce_lap_interface.c b/encoder/ihevce_lap_interface.c
index 4ace17a..734c609 100644
--- a/encoder/ihevce_lap_interface.c
+++ b/encoder/ihevce_lap_interface.c
@@ -1710,7 +1710,7 @@
     }
 
     ps_lap_struct->pv_prev_inp_buf = (void *)ps_lap_out_buf;
-    ps_lap_out_buf->s_lap_out.i4_is_prev_pic_in_Tid0_same_scene = 0;
+    ps_lap_out_buf->s_lap_out.i4_is_prev_pic_in_Tid0_same_scene = 1;
 
     /*with force idr below check is not valid*/
 #if(!FORCE_IDR_TEST)
@@ -2076,6 +2076,10 @@
                 ps_lap_interface->ihevce_dyn_bitrate_cb(
                     (void *)ps_hle_ctxt, (void *)&as_dyn_br[bitrt_ctr]);
             }
+
+            /* release async ctrl buffer*/
+            ihevce_q_rel_buf(
+                ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_ASYNCH_CTRL_Q, ps_ctrl_buf->i4_buf_id);
         }
 
         {
diff --git a/encoder/ihevce_plugin.c b/encoder/ihevce_plugin.c
index cb597d0..df7cee0 100644
--- a/encoder/ihevce_plugin.c
+++ b/encoder/ihevce_plugin.c
@@ -2055,6 +2055,8 @@
                             ps_dyn_br->i4_tgt_res_id = 0;
                             ps_dyn_br->i4_new_tgt_bitrate =
                                 MIN(ps_inp->i4_curr_bitrate, max_bitrate);
+                            ps_dyn_br->i4_new_tgt_bitrate =
+                                MAX(ps_dyn_br->i4_new_tgt_bitrate, MIN_BITRATE);
                             ps_dyn_br->i4_new_peak_bitrate =
                                 MIN((ps_dyn_br->i4_new_tgt_bitrate << 1), max_bitrate);
                             pi4_cmd_buf += 2;
@@ -2067,7 +2069,7 @@
                             /* ---------- set the buffer as produced ---------- */
                             ihevce_q_set_inp_ctrl_buff_prod(ps_interface_ctxt, buf_id);
 
-                            ps_ctxt->ai4_old_bitrate[0][0] = ps_inp->i4_curr_bitrate;
+                            ps_ctxt->ai4_old_bitrate[0][0] = ps_dyn_br->i4_new_tgt_bitrate;
                         }
                     }
 
diff --git a/encoder/ihevce_rc_interface.c b/encoder/ihevce_rc_interface.c
index 17ffa78..b0cee1b 100644
--- a/encoder/ihevce_rc_interface.c
+++ b/encoder/ihevce_rc_interface.c
@@ -4929,13 +4929,11 @@
             &ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc],
             ps_rc_lap_out,
             sizeof(rc_lap_out_params_t));
-        //BUG_FIX related to the releasing of the next lap out buffers and retrieving of the data for the delayed update.
 
         {
-            rc_lap_out_params_t *ps_rc_lap_out_next_encode;
-            ps_rc_lap_out_next_encode =
-                (rc_lap_out_params_t *)((rc_lap_out_params_t *)ps_rc_lap_out)
-                    ->ps_rc_lap_out_next_encode;
+            rc_lap_out_params_t *ps_rc_lap_out_curr = (rc_lap_out_params_t *)ps_rc_lap_out;
+            rc_lap_out_params_t *ps_rc_lap_out_next_encode =
+                (rc_lap_out_params_t *)ps_rc_lap_out_curr->ps_rc_lap_out_next_encode;
 
             if(NULL != ps_rc_lap_out_next_encode)
             {
@@ -4946,12 +4944,19 @@
             }
             else
             {
-                ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc].i4_next_pic_type = -1;
+                if(ps_rc_lap_out_curr->i4_rc_display_num &&
+                   (ps_rc_lap_out_curr->i4_rc_display_num %
+                    (ps_rc_ctxt->u4_intra_frame_interval - 1)) == 0)
+                {
+                    ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc].i4_next_pic_type = IV_I_FRAME;
+                }
+                else
+                {
+                    ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc].i4_next_pic_type = -1;
+                }
                 ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc].i4_next_scene_type = -1;
             }
-
-            ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc].ps_rc_lap_out_next_encode =
-                NULL;  //RC_BUG_FIX
+            ps_rc_ctxt->as_rc_lap_out[i4_enc_frm_id_rc].ps_rc_lap_out_next_encode = NULL;
         }
     }
     else if(2 == i4_store_retrive)
diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp
index 3ea0b85..90b34c8 100644
--- a/fuzzer/Android.bp
+++ b/fuzzer/Android.bp
@@ -13,4 +13,32 @@
             enabled: false,
         },
     },
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
+}
+
+cc_fuzz {
+    name: "hevc_enc_fuzzer",
+    host_supported: true,
+    srcs: [
+        "hevc_enc_fuzzer.cpp",
+    ],
+    static_libs: [
+        "libhevcenc",
+        "liblog",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    fuzz_config: {
+        cc: [
+            "android-media-fuzzing-reports@google.com",
+        ],
+        componentid: 155276,
+    },
 }
diff --git a/fuzzer/README.md b/fuzzer/README.md
index b883e37..49353da 100644
--- a/fuzzer/README.md
+++ b/fuzzer/README.md
@@ -64,6 +64,110 @@
   $ $ANDROID_HOST_OUT/fuzz/hevc_dec_fuzzer CORPUS_DIR
 ```
 
+
+# Fuzzer for libhevc encoder
+
+## Plugin Design Considerations
+The fuzzer plugin for HEVC is designed based on the understanding of the
+codec and tries to achieve the following:
+
+##### Maximize code coverage
+The configuration parameters are not hardcoded, but instead selected based on
+incoming data. This ensures more code paths are reached by the fuzzer.
+
+HEVC supports the following parameters:
+1. Frame Width (parameter name: `i4_width`)
+2. Frame Height (parameter name: `i4_height`)
+3. Intra max transform tree depth (parameter name: `i4_max_tr_tree_depth_I`)
+4. Inter max transform tree depth (parameter name: `i4_max_tr_tree_depth_nI`)
+5. CU level Qp modulation (parameter name: `i4_cu_level_rc`)
+6. Rate control mode (parameter name: `i4_rate_control_mode`)
+7. Frame level Qp (parameter name: `ai4_frame_qp`)
+8. Encoder quality preset (parameter name: `i4_quality_preset`)
+9. Target Bitrate (parameter name: `ai4_tgt_bitrate`)
+10. Enable entropy sync (parameter name: `i4_enable_entropy_sync`)
+11. Deblocking type (parameter name: `i4_deblocking_type`)
+12. Default scaling matrices (parameter name: `i4_use_default_sc_mtx`)
+13. Max temporal layers (parameter name: `i4_max_temporal_layers`)
+14. Max difference b/w IDR frames (parameter name: `i4_max_closed_gop_period`)
+15. Min difference b/w IDR frames (parameter name: `i4_min_closed_gop_period`)
+16. Max difference b/w I frames (parameter name: `i4_max_i_open_gop_period`)
+17. Max difference b/w CRA frames (parameter name: `i4_max_cra_open_gop_period`)
+18. Automatic insertion of SPS at each CDR (parameter name: `i4_sps_at_cdr_enable`)
+19. Enable VUI output (parameter name: `i4_vui_enable`)
+20. Enable SEI messages (parameter name: `i4_sei_enable_flag`)
+21. Architecture type (parameter name: `e_arch_type`)
+22. Enable force IDR frame test(parameter name: `mIsForceIdrEnabled`)
+23. Enable dynamic bitrate test (parameter name: `mIsDynamicBitrateChangeEnabled`)
+24. Force IDR frame number (parameter name: `mForceIdrInterval`)
+25. Frame number for dynamic bitrate  (parameter name: `mDynamicBitrateInterval`)
+
+| Parameter| Valid Values| Configured Value|
+|------------- |-------------| ----- |
+| `i4_width` | In the range `0 to 10239` | All the bits of 1st and 2nd byte of data |
+| `i4_height` | In the range `0 to 10239` | All the bits of 3rd and 4th byte of data |
+| `i4_max_tr_tree_depth_I` | 0. `1` 1. `2` 2. `3` | All the bits of 5th byte of data |
+| `i4_max_tr_tree_depth_nI` | 0. `1` 1. `2` 2. `3` 3. `4` | bit 0 and 1 of 6th byte of data |
+| `i4_cu_level_rc` | 0. `0` 1. `1` | bit 0 of 7th byte of data |
+| `i4_rate_control_mode` | 0. `VBR` 1. `CQP` 2. `CBR` | All the bits of 8th byte of data modulus 3 |
+| `ai4_frame_qp` | In the range `1 to 51` | All the bits of 9th byte of data |
+| `i4_quality_preset` | 0. `IHEVCE_QUALITY_P0` 1. `IHEVCE_QUALITY_P2` 2. `IHEVCE_QUALITY_P3` 3. `IHEVCE_QUALITY_P4 4. `IHEVCE_QUALITY_P5` 5. `IHEVCE_QUALITY_P6` 6. `IHEVCE_QUALITY_P7` | All the bits of 10th byte of data modulus 7 |
+| `ai4_tgt_bitrate` | In the range `0 to 500000000` | All the bits of 11th and 12th byte of data |
+| `i4_enable_entropy_sync` | 0. `0` 1. `1` | bit 0 of 13th byte of data |
+| `i4_deblocking_type` | 0. `0` 1. `1` | bit 0 of 14th byte of data |
+| `i4_use_default_sc_mtx` | 0. `0` 1. `1` | bit 0 of 15th byte of data |
+| `i4_max_temporal_layers` | 0. `0` 1. `1` 2. `2` 3. `3` | bit 0 and 1 of 16th byte of data |
+| `i4_max_closed_gop_period` | In the range `0 to 255` | All the bits of 17th byte of data |
+| `i4_min_closed_gop_period` | In the range `0 to 255` | All the bits of 18th byte of data |
+| `i4_max_i_open_gop_period` | In the range `0 to 255` | All the bits of 19th byte of data |
+| `i4_max_cra_open_gop_period` | In the range `0 to 255` | All the bits of 20th byte of data |
+| `i4_sps_at_cdr_enable` | 0. `0` 1. `1` | bit 0 of 21st byte of data |
+| `i4_vui_enable` | 0. `0` 1. `1` | bit 0 of 22nd byte of data |
+| `i4_sei_enable_flag` | 0. `0` 1. `1` | bit 0 of 23th byte of data |
+| `e_arch_type` | 0. `ARCH_ARM_NONEON` 1. `ARCH_NA` | bit 0 and 1 of 24th byte of data |
+| `mIsForceIdrEnabled` | 0. `0` 1. `1` | bit 0 of 25th byte of data |
+| `mIsDynamicBitrateChangeEnabled` | 0. `0` 1. `1` | bit 0 of 	 byte of data |
+| `mForceIdrInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 27th byte of data |
+| `mDynamicBitrateInterval` | In the range `0 to 7` | bit 0, 1 and 2 of 28th byte of data |
+
+This also ensures that the plugin is always deterministic for any given input.
+
+##### Maximize utilization of input data
+The plugin feeds the entire input data to the codec using a loop.
+If the encode operation was successful, the input is advanced by the frame size.
+If the encode operation was un-successful, the input is still advanced by frame size so
+that the fuzzer can proceed to feed the next frame.
+
+This ensures that the plugin tolerates any kind of input (empty, huge,
+malformed, etc) and doesnt `exit()` on any input and thereby increasing the
+chance of identifying vulnerabilities.
+
+## Build
+
+This describes steps to build hevc_enc_fuzzer binary.
+
+### Android
+
+#### Steps to build
+Build the fuzzer
+```
+  $ mm -j$(nproc) hevc_enc_fuzzer
+```
+
+#### Steps to run
+Create a directory CORPUS_DIR and copy some yuv files to that folder
+Push this directory to device.
+
+To run on device
+```
+  $ adb sync data
+  $ adb shell /data/fuzz/arm64/hevc_enc_fuzzer/hevc_enc_fuzzer CORPUS_DIR
+```
+To run on host
+```
+  $ $ANDROID_HOST_OUT/fuzz/x86_64/hevc_enc_fuzzer/hevc_enc_fuzzer CORPUS_DIR
+```
+
 ## References:
  * http://llvm.org/docs/LibFuzzer.html
  * https://github.com/google/oss-fuzz
diff --git a/fuzzer/hevc_enc_fuzzer.cpp b/fuzzer/hevc_enc_fuzzer.cpp
new file mode 100644
index 0000000..9d0d370
--- /dev/null
+++ b/fuzzer/hevc_enc_fuzzer.cpp
@@ -0,0 +1,220 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2020 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 <algorithm>
+#include <memory>
+
+#include "ihevc_typedefs.h"
+#include "itt_video_api.h"
+#include "ihevce_api.h"
+#include "ihevce_plugin.h"
+#include "ihevce_profile.h"
+
+constexpr size_t kRcType[] = {2, 3, 5};
+constexpr IHEVCE_QUALITY_CONFIG_T kQuality[] = {
+    IHEVCE_QUALITY_P0, IHEVCE_QUALITY_P2, IHEVCE_QUALITY_P3, IHEVCE_QUALITY_P4,
+    IHEVCE_QUALITY_P5, IHEVCE_QUALITY_P6, IHEVCE_QUALITY_P7};
+
+constexpr size_t kRcTypeNum = std::size(kRcType);
+constexpr size_t kQualityNum = std::size(kQuality);
+constexpr size_t kMaxQP = 51;
+constexpr size_t kMaxGopPeriod = 16;
+constexpr size_t kMaxWidth = 10240;
+constexpr size_t kMaxHeight = 10240;
+constexpr size_t kMaxBitrate = 500000000;
+
+enum {
+    IDX_WD_BYTE_1,
+    IDX_WD_BYTE_2,
+    IDX_HT_BYTE_1,
+    IDX_HT_BYTE_2,
+    IDX_MAX_INTRA_TX_DEPTH,
+    IDX_MAX_INTER_TX_DEPTH,
+    IDX_CU_RC,
+    IDX_RC_MODE,
+    IDX_FRAME_QP,
+    IDX_PRESET,
+    IDX_BITRATE_BYTE_1,
+    IDX_BITRATE_BYTE_2,
+    IDX_ENABLE_ENTROPY_SYNC,
+    IDX_DEBLOCKING_TYPE,
+    IDX_USE_SC_MTX,
+    IDX_MAX_TEMPORAL_LAYERS,
+    IDX_MAX_CLOSED_GOP,
+    IDX_MIN_CLOSED_GOP,
+    IDX_MAX_I_OPEN_GOP,
+    IDX_MAX_CRA_OPEN_GOP,
+    IDX_ENABLE_SPS_AT_CDR,
+    IDX_ENABLE_VUI,
+    IDX_ENABLE_SEI,
+    IDX_ARCH_TYPE,
+    IDX_ENABLE_FORCE_IDR,
+    IDX_ENABLE_DYNAMIC_BITRATE,
+    IDX_FORCE_IDR_INTERVAL,
+    IDX_DYNAMIC_BITRATE_INTERVAL,
+    IDX_LAST
+};
+
+class Codec {
+   public:
+    Codec() = default;
+    ~Codec() { deInitEncoder(); }
+    bool initEncoder(const uint8_t *data);
+    void deInitEncoder();
+    void encodeFrames(const uint8_t *data, size_t size);
+
+   private:
+    bool mIsForceIdrEnabled = false;
+    bool mIsDynamicBitrateChangeEnabled = false;
+    size_t mWidth = 352;
+    size_t mHeight = 288;
+    size_t mForceIdrInterval = 0;        // in number of frames
+    size_t mDynamicBitrateInterval = 0;  // in number of frames
+    uint64_t mBitrate = 5000000;
+    void *mCodecCtx = nullptr;
+    ihevce_static_cfg_params_t mEncParams = {};
+};
+
+bool Codec::initEncoder(const uint8_t *data) {
+    // default configuration
+    if (IHEVCE_EOK != ihevce_set_def_params(&mEncParams)) {
+        return false;
+    }
+    mWidth = ((data[IDX_WD_BYTE_1] << 8) | data[IDX_WD_BYTE_2]) % kMaxWidth;
+    mHeight = ((data[IDX_HT_BYTE_1] << 8) | data[IDX_HT_BYTE_2]) % kMaxHeight;
+
+    // update configuration
+    mEncParams.s_src_prms.i4_width = mWidth;
+    mEncParams.s_src_prms.i4_height = mHeight;
+
+    mEncParams.s_config_prms.i4_max_tr_tree_depth_I = (data[IDX_MAX_INTRA_TX_DEPTH] % 3) + 1;
+    mEncParams.s_config_prms.i4_max_tr_tree_depth_nI = (data[IDX_MAX_INTER_TX_DEPTH] & 0x03) + 1;
+    mEncParams.s_config_prms.i4_cu_level_rc = data[IDX_CU_RC] & 0x01;
+    mEncParams.s_config_prms.i4_rate_control_mode = kRcType[data[IDX_RC_MODE] % kRcTypeNum];
+
+    mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_frame_qp[0] = (data[IDX_FRAME_QP] % kMaxQP) + 1;
+    mEncParams.s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset =
+        kQuality[data[IDX_PRESET] % kQualityNum];
+    mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_tgt_bitrate[0] =
+        (((data[IDX_BITRATE_BYTE_1] << 8) | data[IDX_BITRATE_BYTE_2]) * 1000) % kMaxBitrate;
+    mEncParams.s_tgt_lyr_prms.as_tgt_params[0].ai4_peak_bitrate[0] =
+        ((((data[IDX_BITRATE_BYTE_1] << 8) | data[IDX_BITRATE_BYTE_2]) * 1000) % kMaxBitrate) << 1;
+    mEncParams.s_coding_tools_prms.i4_enable_entropy_sync = data[IDX_ENABLE_ENTROPY_SYNC] & 0x01;
+    mEncParams.s_coding_tools_prms.i4_deblocking_type = data[IDX_DEBLOCKING_TYPE] & 0x01;
+    mEncParams.s_coding_tools_prms.i4_use_default_sc_mtx = data[IDX_USE_SC_MTX] & 0x01;
+    mEncParams.s_coding_tools_prms.i4_max_temporal_layers = data[IDX_MAX_TEMPORAL_LAYERS] & 0x02;
+    mEncParams.s_coding_tools_prms.i4_max_closed_gop_period =
+        data[IDX_MAX_CLOSED_GOP] % kMaxGopPeriod;
+    mEncParams.s_coding_tools_prms.i4_min_closed_gop_period =
+        data[IDX_MIN_CLOSED_GOP] % kMaxGopPeriod;
+    mEncParams.s_coding_tools_prms.i4_max_i_open_gop_period =
+        data[IDX_MAX_I_OPEN_GOP] % kMaxGopPeriod;
+    mEncParams.s_coding_tools_prms.i4_max_cra_open_gop_period =
+        data[IDX_MAX_CRA_OPEN_GOP] % kMaxGopPeriod;
+
+    mEncParams.s_out_strm_prms.i4_sps_at_cdr_enable = data[IDX_ENABLE_SPS_AT_CDR] & 0x01;
+    mEncParams.s_out_strm_prms.i4_vui_enable = data[IDX_ENABLE_VUI] & 0x01;
+    mEncParams.s_out_strm_prms.i4_sei_enable_flag = data[IDX_ENABLE_SEI] & 0x01;
+
+    mEncParams.e_arch_type = ((data[IDX_ARCH_TYPE] & 0x03) == 0x00) ? ARCH_ARM_NONEON : ARCH_NA;
+    mIsForceIdrEnabled = data[IDX_ENABLE_FORCE_IDR] & 0x01;
+    mIsDynamicBitrateChangeEnabled = data[IDX_ENABLE_DYNAMIC_BITRATE] & 0x01;
+    mForceIdrInterval = data[IDX_FORCE_IDR_INTERVAL] & 0x07;
+    mDynamicBitrateInterval = data[IDX_DYNAMIC_BITRATE_INTERVAL] & 0x07;
+
+    if (IHEVCE_EOK != ihevce_init(&mEncParams, &mCodecCtx)) {
+        return false;
+    }
+    return true;
+}
+
+void Codec::encodeFrames(const uint8_t *data, size_t size) {
+    size_t frameSize = (mWidth * mHeight * 3) / 2;
+
+    ihevce_out_buf_t sHeaderOp{};
+    ihevce_encode_header(mCodecCtx, &sHeaderOp);
+    size_t frameNumber = 0;
+    uint8_t *tmpData = new uint8_t[frameSize];
+    while (size > 0) {
+        ihevce_inp_buf_t sEncodeIp{};
+        ihevce_out_buf_t sEncodeOp{};
+        size_t bytesConsumed = std::min(size, frameSize);
+        if (bytesConsumed < frameSize) {
+            memset(&tmpData[bytesConsumed], data[0], frameSize - bytesConsumed);
+        }
+        memcpy(tmpData, data, bytesConsumed);
+        int32_t yStride = mWidth;
+        int32_t uStride = mWidth >> 1;
+        int32_t vStride = mWidth >> 1;
+
+        sEncodeIp.apv_inp_planes[0] = tmpData;
+        sEncodeIp.apv_inp_planes[1] = tmpData + (mWidth * mHeight);
+        sEncodeIp.apv_inp_planes[2] = tmpData + ((mWidth * mHeight) * 5) / 4;
+
+        sEncodeIp.ai4_inp_strd[0] = yStride;
+        sEncodeIp.ai4_inp_strd[1] = uStride;
+        sEncodeIp.ai4_inp_strd[2] = vStride;
+
+        sEncodeIp.ai4_inp_size[0] = yStride * mHeight;
+        sEncodeIp.ai4_inp_size[1] = uStride * mHeight >> 1;
+        sEncodeIp.ai4_inp_size[2] = vStride * mHeight >> 1;
+
+        sEncodeIp.i4_force_idr_flag = 0;
+        sEncodeIp.i4_curr_bitrate = mBitrate;
+        sEncodeIp.i4_curr_peak_bitrate = mBitrate << 1;
+        sEncodeIp.u8_pts = 0;
+        if (mIsForceIdrEnabled) {
+            if (frameNumber == mForceIdrInterval) {
+                sEncodeIp.i4_force_idr_flag = 1;
+            }
+        }
+        if (mIsDynamicBitrateChangeEnabled) {
+            if (frameNumber == mDynamicBitrateInterval) {
+                mBitrate = mBitrate << 1;
+            }
+        }
+        ihevce_encode(mCodecCtx, &sEncodeIp, &sEncodeOp);
+        ++frameNumber;
+        data += bytesConsumed;
+        size -= bytesConsumed;
+    }
+    delete[] tmpData;
+}
+
+void Codec::deInitEncoder() {
+    if (mCodecCtx) {
+        ihevce_close(mCodecCtx);
+        mCodecCtx = nullptr;
+    }
+    return;
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+    if (size < IDX_LAST) {
+        return 0;
+    }
+    Codec *codec = new Codec();
+    if (codec->initEncoder(data)) {
+        data += IDX_LAST;
+        size -= IDX_LAST;
+        codec->encodeFrames(data, size);
+    }
+    delete codec;
+    return 0;
+}
diff --git a/libhevc_blacklist.txt b/libhevc_blocklist.txt
similarity index 100%
rename from libhevc_blacklist.txt
rename to libhevc_blocklist.txt
diff --git a/test/encoder/main.c b/test/encoder/main.c
index 796724f..49d1aec 100644
--- a/test/encoder/main.c
+++ b/test/encoder/main.c
@@ -800,7 +800,10 @@
 #ifdef X86_MINGW
     pu1_buf = (UWORD8 *)_aligned_malloc(pic_size, 64);
 #else
-    posix_memalign((void **)&pu1_buf, 64, pic_size);
+    if (0 != posix_memalign((void **)&pu1_buf, 64, pic_size))
+    {
+        return (IHEVCE_EFAIL);
+    }
 #endif
     if(NULL == pu1_buf)
     {