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)
{