blob: 501d177a004ce2069abb8c683553dd24c4d5bf59 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <stddef.h>
#include "ldacBT.h"
#include <fuzzer/FuzzedDataProvider.h>
#include <vector>
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 kOutputSize = 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;
private:
int32_t mChannel;
LDACBT_SMPL_FMT_T mFormat;
HANDLE_LDAC_BT mHandleLdacBt;
};
bool Codec::initEncoder() {
mHandleLdacBt = ldacBT_get_handle();
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;
}
}
void Codec::getSamplingFrequeny() { ldacBT_get_sampling_freq(mHandleLdacBt); }
void Codec::getBitrate() { ldacBT_get_bitrate(mHandleLdacBt); }
void Codec::getVersion() { ldacBT_get_version(); }
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;
}