libldac-encode_fuzzer: Updated the fuzzer am: 876dfce35e

Original change: https://android-review.googlesource.com/c/platform/external/libldac/+/2015997

Change-Id: I85014fb097d4e05018334cd1522fcea8525f7cc5
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/fuzzer/libldac_encode_fuzzer.cc b/fuzzer/libldac_encode_fuzzer.cc
index 51d8729..501d177 100644
--- a/fuzzer/libldac_encode_fuzzer.cc
+++ b/fuzzer/libldac_encode_fuzzer.cc
@@ -6,55 +6,105 @@
 #include <stddef.h>
 #include "ldacBT.h"
 
-#include <string.h>
+#include <fuzzer/FuzzedDataProvider.h>
 #include <vector>
 
-#define TESTFUNC_TYPE extern "C" int
+constexpr LDACBT_SMPL_FMT_T kFormat[] = {
+    LDACBT_SMPL_FMT_S16, LDACBT_SMPL_FMT_S24, LDACBT_SMPL_FMT_S32,
+    LDACBT_SMPL_FMT_F32};
+constexpr int32_t kEqmidValue[] = {LDACBT_EQMID_HQ, LDACBT_EQMID_SQ,
+                                   LDACBT_EQMID_MQ};
+constexpr int32_t kChannel[] = {LDACBT_CHANNEL_MODE_STEREO,
+                                LDACBT_CHANNEL_MODE_DUAL_CHANNEL,
+                                LDACBT_CHANNEL_MODE_MONO};
+constexpr int32_t kSamplingFrequency[] = {44100, 48000, 2 * 44100, 2 * 48000};
+constexpr int32_t kLdacBtRequiredMtu = 679;
 constexpr int32_t kMaxWlValue = 4;
+constexpr int32_t kMinChValue = 1;
 constexpr int32_t kMaxChValue = 2;
-constexpr int32_t kMaxFrameSize = LDACBT_ENC_LSU * kMaxWlValue * kMaxChValue;
+constexpr int32_t kOutputSize = 1024;
 
-TESTFUNC_TYPE
-LLVMFuzzerTestOneInput(const uint8_t *buf, size_t size)
-{
-    if (size == 0) {
-    	return 0;
-    }
-    HANDLE_LDAC_BT hLdacBt;
-    int pcm_used, stream_sz, frame_num;
-    unsigned char p_stream[1024];
+class Codec {
+public:
+  Codec(const uint8_t *data, size_t size) : mFdp(data, size){};
+  ~Codec() { deInitEncoder(); }
+  bool initEncoder();
+  void deInitEncoder();
+  void encodeFrames(const uint8_t *data, size_t size);
+  void getSamplingFrequeny();
+  void getBitrate();
+  void getVersion();
+  FuzzedDataProvider mFdp;
 
-    hLdacBt = ldacBT_get_handle();
+private:
+  int32_t mChannel;
+  LDACBT_SMPL_FMT_T mFormat;
+  HANDLE_LDAC_BT mHandleLdacBt;
+};
 
-    ldacBT_init_handle_encode(
-        hLdacBt,
-        679,
-        LDACBT_EQMID_SQ,
-        LDACBT_CHANNEL_MODE_DUAL_CHANNEL,
-        LDACBT_SMPL_FMT_S16,
-        48000);
-    uint8_t *readPointer = const_cast<uint8_t *>(buf);
-    std::vector<uint8_t> tmpData(kMaxFrameSize);
+bool Codec::initEncoder() {
+  mHandleLdacBt = ldacBT_get_handle();
 
-    if (size < kMaxFrameSize) {
-      memcpy(tmpData.data(), buf, size);
+  mChannel = mFdp.PickValueInArray(kChannel);
+  mFormat = mFdp.PickValueInArray(kFormat);
+  int32_t status = ldacBT_init_handle_encode(
+      mHandleLdacBt, kLdacBtRequiredMtu, mFdp.PickValueInArray(kEqmidValue),
+      mChannel, mFormat, mFdp.PickValueInArray(kSamplingFrequency));
+  if (!status) {
+    return true;
+  }
+  return false;
+}
+
+void Codec::encodeFrames(const uint8_t *data, size_t size) {
+  int32_t pcmUsed, streamSize, frameNum;
+  unsigned char pStream[kOutputSize];
+  int32_t ch, wl, frameSize;
+  ch = (mChannel == LDAC_CCI_MONO) ? kMinChValue : kMaxChValue;
+  wl = mFormat > kMaxWlValue ? kMaxWlValue : mFormat;
+  frameSize = LDACBT_ENC_LSU * ch * wl;
+  std::vector<uint8_t> tmpData(frameSize);
+  uint8_t *readPointer = const_cast<uint8_t *>(data);
+  while (size > 0) {
+    if (size < frameSize) {
+      memcpy(tmpData.data(), data, size);
+      size = frameSize;
       readPointer = tmpData.data();
     }
+    ldacBT_encode(mHandleLdacBt, readPointer, &pcmUsed, pStream, &streamSize,
+                  &frameNum);
+    readPointer += frameSize;
+    size -= frameSize;
+  }
+}
 
-    ldacBT_encode(
-        hLdacBt,
-        readPointer,
-        &pcm_used,
-        p_stream,
-        &stream_sz,
-        &frame_num);
+void Codec::getSamplingFrequeny() { ldacBT_get_sampling_freq(mHandleLdacBt); }
 
-    ldacBT_get_sampling_freq(hLdacBt);
-    ldacBT_get_bitrate(hLdacBt);
-    ldacBT_get_version();
+void Codec::getBitrate() { ldacBT_get_bitrate(mHandleLdacBt); }
 
-    ldacBT_close_handle(hLdacBt);
-    ldacBT_free_handle(hLdacBt);
+void Codec::getVersion() { ldacBT_get_version(); }
 
-    return 0;
+void Codec::deInitEncoder() {
+  ldacBT_close_handle(mHandleLdacBt);
+  ldacBT_free_handle(mHandleLdacBt);
+}
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t size) {
+  Codec codec(buf, size);
+  /* initEncoder() initializes mHandleLdacBt and is supposed to be called before
+     encoding begins. Hence initEncoder() is not included in the lambda
+     construct. */
+  if (codec.initEncoder()) {
+    while (codec.mFdp.remaining_bytes() > 0) {
+      auto executeFunction =
+          codec.mFdp.PickValueInArray<const std::function<void()>>({
+              [&]() { codec.encodeFrames(buf, size); },
+              [&]() { codec.getSamplingFrequeny(); },
+              [&]() { codec.getBitrate(); },
+              [&]() { codec.getVersion(); },
+          });
+      executeFunction();
+    }
+  }
+  return 0;
 }