1*600f14f4SXin Li /******************************************************************************
2*600f14f4SXin Li *
3*600f14f4SXin Li * Copyright (C) 2020 The Android Open Source Project
4*600f14f4SXin Li *
5*600f14f4SXin Li * Licensed under the Apache License, Version 2.0 (the "License");
6*600f14f4SXin Li * you may not use this file except in compliance with the License.
7*600f14f4SXin Li * You may obtain a copy of the License at:
8*600f14f4SXin Li *
9*600f14f4SXin Li * http://www.apache.org/licenses/LICENSE-2.0
10*600f14f4SXin Li *
11*600f14f4SXin Li * Unless required by applicable law or agreed to in writing, software
12*600f14f4SXin Li * distributed under the License is distributed on an "AS IS" BASIS,
13*600f14f4SXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*600f14f4SXin Li * See the License for the specific language governing permissions and
15*600f14f4SXin Li * limitations under the License.
16*600f14f4SXin Li *
17*600f14f4SXin Li *****************************************************************************
18*600f14f4SXin Li * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*600f14f4SXin Li */
20*600f14f4SXin Li
21*600f14f4SXin Li #include <math.h>
22*600f14f4SXin Li #include <stdlib.h>
23*600f14f4SXin Li #include <algorithm>
24*600f14f4SXin Li
25*600f14f4SXin Li #include "FLAC/stream_encoder.h"
26*600f14f4SXin Li #include "audio_utils/primitives.h"
27*600f14f4SXin Li #include "share/compat.h"
28*600f14f4SXin Li
29*600f14f4SXin Li constexpr int kMinSampleRate = 1;
30*600f14f4SXin Li constexpr int kFramesPerBlock = 1152;
31*600f14f4SXin Li constexpr int kMaxSampleRate = 655350;
32*600f14f4SXin Li constexpr uint8_t kMinNumChannels = 1;
33*600f14f4SXin Li constexpr uint8_t kMaxNumChannels = 2;
34*600f14f4SXin Li constexpr uint8_t kMinCompressionLevel = 0;
35*600f14f4SXin Li constexpr uint8_t kMaxCompressionLevel = 8;
36*600f14f4SXin Li
37*600f14f4SXin Li enum Encoding { PCM_16, PCM_FLOAT };
38*600f14f4SXin Li
39*600f14f4SXin Li enum {
40*600f14f4SXin Li IDX_SAMPLE_RATE_INDEX_1 = 0,
41*600f14f4SXin Li IDX_SAMPLE_RATE_INDEX_2,
42*600f14f4SXin Li IDX_SAMPLE_RATE_INDEX_3,
43*600f14f4SXin Li IDX_CHANNEL,
44*600f14f4SXin Li IDX_COMPRESSION_LEVEL,
45*600f14f4SXin Li IDX_PCM,
46*600f14f4SXin Li IDX_SET_VERIFY,
47*600f14f4SXin Li IDX_SET_STREAMABLE_SUBSET,
48*600f14f4SXin Li IDX_SET_DO_MID_SIDE_STEREO,
49*600f14f4SXin Li IDX_SET_LOOSE_MID_SIDE_STEREO,
50*600f14f4SXin Li IDX_SET_MAX_LPC_ORDER,
51*600f14f4SXin Li IDX_SET_COEFF_PRECISION,
52*600f14f4SXin Li IDX_SET_COEFF_PREC_SEARCH,
53*600f14f4SXin Li IDX_SET_DO_ESCAPE_CODING,
54*600f14f4SXin Li IDX_SET_DO_EXHAUSTIVE_MODEL_SEARCH,
55*600f14f4SXin Li IDX_SET_MIN_RESIDUAL_PARTITION_ORDER,
56*600f14f4SXin Li IDX_SET_MAX_RESIDUAL_PARTITION_ORDER,
57*600f14f4SXin Li IDX_SET_RICE_PARAMETER_SEARCH_DIST,
58*600f14f4SXin Li IDX_SET_TOTAL_SAMPLES_ESTIMATE,
59*600f14f4SXin Li IDX_LAST
60*600f14f4SXin Li };
61*600f14f4SXin Li
62*600f14f4SXin Li class Codec {
63*600f14f4SXin Li public:
~Codec()64*600f14f4SXin Li ~Codec() { deInitEncoder(); }
65*600f14f4SXin Li bool initEncoder(uint8_t **dataPtr, size_t *sizePtr);
66*600f14f4SXin Li void encodeFrames(const uint8_t *data, size_t size);
67*600f14f4SXin Li void deInitEncoder();
68*600f14f4SXin Li static FLAC__StreamEncoderWriteStatus flacEncoderWriteCallback(
69*600f14f4SXin Li const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes,
70*600f14f4SXin Li unsigned samples, unsigned current_frame, void *client_data);
71*600f14f4SXin Li
72*600f14f4SXin Li private:
73*600f14f4SXin Li bool verifyStateAndReturn();
74*600f14f4SXin Li FLAC__StreamEncoder *mFlacStreamEncoder = nullptr;
75*600f14f4SXin Li uint32_t mChannels = 0;
76*600f14f4SXin Li uint32_t mPcmEncodingInfo = 0;
77*600f14f4SXin Li FLAC__int32 mInputBufferPcm32[kFramesPerBlock * kMaxNumChannels] = {};
78*600f14f4SXin Li };
79*600f14f4SXin Li
flacEncoderWriteCallback(const FLAC__StreamEncoder * encoder,const FLAC__byte buffer[],size_t bytes,unsigned samples,unsigned current_frame,void * client_data)80*600f14f4SXin Li FLAC__StreamEncoderWriteStatus Codec::flacEncoderWriteCallback(const FLAC__StreamEncoder *encoder,
81*600f14f4SXin Li const FLAC__byte buffer[],
82*600f14f4SXin Li size_t bytes, unsigned samples,
83*600f14f4SXin Li unsigned current_frame,
84*600f14f4SXin Li void *client_data) {
85*600f14f4SXin Li (void)encoder;
86*600f14f4SXin Li (void)buffer;
87*600f14f4SXin Li (void)bytes;
88*600f14f4SXin Li (void)samples;
89*600f14f4SXin Li (void)current_frame;
90*600f14f4SXin Li (void)client_data;
91*600f14f4SXin Li return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
92*600f14f4SXin Li }
93*600f14f4SXin Li
verifyStateAndReturn()94*600f14f4SXin Li bool Codec::verifyStateAndReturn() {
95*600f14f4SXin Li FLAC__StreamEncoderState state = FLAC__stream_encoder_get_state(mFlacStreamEncoder);
96*600f14f4SXin Li if (state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR) {
97*600f14f4SXin Li FLAC__stream_encoder_get_verify_decoder_state(mFlacStreamEncoder);
98*600f14f4SXin Li }
99*600f14f4SXin Li return false;
100*600f14f4SXin Li }
101*600f14f4SXin Li
102*600f14f4SXin Li template <typename type1, typename type2, typename type3>
generateNumberInRangeFromData(type1 data,type2 min,type3 max)103*600f14f4SXin Li auto generateNumberInRangeFromData(type1 data, type2 min, type3 max) -> decltype(max) {
104*600f14f4SXin Li return (data % (1 + max - min)) + min;
105*600f14f4SXin Li }
106*600f14f4SXin Li
initEncoder(uint8_t ** dataPtr,size_t * sizePtr)107*600f14f4SXin Li bool Codec::initEncoder(uint8_t **dataPtr, size_t *sizePtr) {
108*600f14f4SXin Li uint8_t *data = *dataPtr;
109*600f14f4SXin Li mFlacStreamEncoder = FLAC__stream_encoder_new();
110*600f14f4SXin Li if (!mFlacStreamEncoder) {
111*600f14f4SXin Li return false;
112*600f14f4SXin Li }
113*600f14f4SXin Li
114*600f14f4SXin Li // Clubbing 3 bytes of data to ensure sample rate in the range [1, 655350]
115*600f14f4SXin Li uint32_t tempValue = (data[IDX_SAMPLE_RATE_INDEX_1] << 16) |
116*600f14f4SXin Li (data[IDX_SAMPLE_RATE_INDEX_2] << 8) | data[IDX_SAMPLE_RATE_INDEX_3];
117*600f14f4SXin Li uint32_t sampleRate = generateNumberInRangeFromData(tempValue, kMinSampleRate, kMaxSampleRate);
118*600f14f4SXin Li FLAC__stream_encoder_set_sample_rate(mFlacStreamEncoder, sampleRate);
119*600f14f4SXin Li
120*600f14f4SXin Li mChannels = generateNumberInRangeFromData(data[IDX_CHANNEL], kMinNumChannels, kMaxNumChannels);
121*600f14f4SXin Li FLAC__stream_encoder_set_channels(mFlacStreamEncoder, mChannels);
122*600f14f4SXin Li
123*600f14f4SXin Li int compression = generateNumberInRangeFromData(data[IDX_COMPRESSION_LEVEL],
124*600f14f4SXin Li kMinCompressionLevel, kMaxCompressionLevel);
125*600f14f4SXin Li FLAC__stream_encoder_set_compression_level(mFlacStreamEncoder, compression);
126*600f14f4SXin Li
127*600f14f4SXin Li uint32_t pcmEncodingInfo =
128*600f14f4SXin Li generateNumberInRangeFromData(data[IDX_PCM], (int)PCM_16, (int)PCM_FLOAT);
129*600f14f4SXin Li mPcmEncodingInfo = pcmEncodingInfo;
130*600f14f4SXin Li uint32_t bitsPerSample = (mPcmEncodingInfo == PCM_FLOAT) ? 24 : 16;
131*600f14f4SXin Li FLAC__stream_encoder_set_bits_per_sample(mFlacStreamEncoder, bitsPerSample);
132*600f14f4SXin Li
133*600f14f4SXin Li int ver = data[IDX_SET_VERIFY] % 2;
134*600f14f4SXin Li FLAC__stream_encoder_set_verify(mFlacStreamEncoder, ver);
135*600f14f4SXin Li
136*600f14f4SXin Li int streamableSubset = data[IDX_SET_STREAMABLE_SUBSET] % 2;
137*600f14f4SXin Li FLAC__stream_encoder_set_streamable_subset(mFlacStreamEncoder, streamableSubset);
138*600f14f4SXin Li
139*600f14f4SXin Li int doMidSideStereo = data[IDX_SET_DO_MID_SIDE_STEREO] % 2;
140*600f14f4SXin Li FLAC__stream_encoder_set_do_mid_side_stereo(mFlacStreamEncoder, doMidSideStereo);
141*600f14f4SXin Li
142*600f14f4SXin Li int looseMidSideStereo = data[IDX_SET_LOOSE_MID_SIDE_STEREO] % 2;
143*600f14f4SXin Li FLAC__stream_encoder_set_loose_mid_side_stereo(mFlacStreamEncoder, looseMidSideStereo);
144*600f14f4SXin Li
145*600f14f4SXin Li int maxLpcOrder = data[IDX_SET_MAX_LPC_ORDER] % 2;
146*600f14f4SXin Li FLAC__stream_encoder_set_max_lpc_order(mFlacStreamEncoder, maxLpcOrder);
147*600f14f4SXin Li
148*600f14f4SXin Li int coeffPrec = data[IDX_SET_COEFF_PRECISION] % 2;
149*600f14f4SXin Li FLAC__stream_encoder_set_qlp_coeff_precision(mFlacStreamEncoder, coeffPrec);
150*600f14f4SXin Li
151*600f14f4SXin Li int coeffPrecSearch = data[IDX_SET_COEFF_PREC_SEARCH] % 2;
152*600f14f4SXin Li FLAC__stream_encoder_set_do_qlp_coeff_prec_search(mFlacStreamEncoder, coeffPrecSearch);
153*600f14f4SXin Li
154*600f14f4SXin Li int escCoding = data[IDX_SET_DO_ESCAPE_CODING] % 2;
155*600f14f4SXin Li FLAC__stream_encoder_set_do_escape_coding(mFlacStreamEncoder, escCoding);
156*600f14f4SXin Li
157*600f14f4SXin Li int exhaustiveModelSearch = data[IDX_SET_DO_EXHAUSTIVE_MODEL_SEARCH] % 2;
158*600f14f4SXin Li FLAC__stream_encoder_set_do_exhaustive_model_search(mFlacStreamEncoder, exhaustiveModelSearch);
159*600f14f4SXin Li
160*600f14f4SXin Li int minResidualPartitionOrder = data[IDX_SET_MIN_RESIDUAL_PARTITION_ORDER] % 2;
161*600f14f4SXin Li FLAC__stream_encoder_set_min_residual_partition_order(mFlacStreamEncoder,
162*600f14f4SXin Li minResidualPartitionOrder);
163*600f14f4SXin Li
164*600f14f4SXin Li int maxResidualPartitionOrder = data[IDX_SET_MAX_RESIDUAL_PARTITION_ORDER] % 2;
165*600f14f4SXin Li FLAC__stream_encoder_set_max_residual_partition_order(mFlacStreamEncoder,
166*600f14f4SXin Li maxResidualPartitionOrder);
167*600f14f4SXin Li
168*600f14f4SXin Li int riceParam = data[IDX_SET_RICE_PARAMETER_SEARCH_DIST] % 2;
169*600f14f4SXin Li FLAC__stream_encoder_set_rice_parameter_search_dist(mFlacStreamEncoder, riceParam);
170*600f14f4SXin Li
171*600f14f4SXin Li int totalSamplesEstimate = data[IDX_SET_TOTAL_SAMPLES_ESTIMATE] % 2;
172*600f14f4SXin Li FLAC__stream_encoder_set_total_samples_estimate(mFlacStreamEncoder, totalSamplesEstimate);
173*600f14f4SXin Li
174*600f14f4SXin Li FLAC__StreamEncoderInitStatus status = FLAC__stream_encoder_init_stream(
175*600f14f4SXin Li mFlacStreamEncoder, flacEncoderWriteCallback /*write_callback*/, nullptr /*seek_callback*/,
176*600f14f4SXin Li nullptr /*tell_callback*/, nullptr /*metadata_callback*/, (void *)this /*client_data*/);
177*600f14f4SXin Li
178*600f14f4SXin Li if (status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
179*600f14f4SXin Li return verifyStateAndReturn();
180*600f14f4SXin Li }
181*600f14f4SXin Li
182*600f14f4SXin Li // Not re-using the data which was used for configuration for encoding
183*600f14f4SXin Li *dataPtr += IDX_LAST;
184*600f14f4SXin Li *sizePtr -= IDX_LAST;
185*600f14f4SXin Li return true;
186*600f14f4SXin Li }
187*600f14f4SXin Li
encodeFrames(const uint8_t * data,size_t size)188*600f14f4SXin Li void Codec::encodeFrames(const uint8_t *data, size_t size) {
189*600f14f4SXin Li size_t sampleSize = (mPcmEncodingInfo == PCM_FLOAT) ? sizeof(float) : sizeof(int16_t);
190*600f14f4SXin Li size_t frameSize = mChannels * sampleSize;
191*600f14f4SXin Li do {
192*600f14f4SXin Li const size_t bytesConsumed = std::min(kFramesPerBlock * frameSize, size);
193*600f14f4SXin Li const unsigned inputFrames = bytesConsumed / frameSize;
194*600f14f4SXin Li const unsigned inputSamples = inputFrames * mChannels;
195*600f14f4SXin Li if (mPcmEncodingInfo == PCM_FLOAT) {
196*600f14f4SXin Li const float *const pcmFloat = reinterpret_cast<const float *>(data);
197*600f14f4SXin Li memcpy_to_q8_23_from_float_with_clamp(mInputBufferPcm32, pcmFloat, inputSamples);
198*600f14f4SXin Li } else {
199*600f14f4SXin Li const int16_t *const pcm16 = reinterpret_cast<const int16_t *>(data);
200*600f14f4SXin Li for (unsigned i = 0; i < inputSamples; ++i) {
201*600f14f4SXin Li mInputBufferPcm32[i] = (FLAC__int32)pcm16[i];
202*600f14f4SXin Li }
203*600f14f4SXin Li }
204*600f14f4SXin Li FLAC__stream_encoder_process_interleaved(mFlacStreamEncoder, mInputBufferPcm32,
205*600f14f4SXin Li inputFrames);
206*600f14f4SXin Li data += bytesConsumed;
207*600f14f4SXin Li size -= bytesConsumed;
208*600f14f4SXin Li } while (size > 0);
209*600f14f4SXin Li }
210*600f14f4SXin Li
deInitEncoder()211*600f14f4SXin Li void Codec::deInitEncoder() {
212*600f14f4SXin Li if (mFlacStreamEncoder) {
213*600f14f4SXin Li FLAC__stream_encoder_finish(mFlacStreamEncoder);
214*600f14f4SXin Li FLAC__stream_encoder_delete(mFlacStreamEncoder);
215*600f14f4SXin Li mFlacStreamEncoder = nullptr;
216*600f14f4SXin Li }
217*600f14f4SXin Li }
218*600f14f4SXin Li
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)219*600f14f4SXin Li extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
220*600f14f4SXin Li if (size < IDX_LAST) {
221*600f14f4SXin Li return 0;
222*600f14f4SXin Li }
223*600f14f4SXin Li Codec encoder;
224*600f14f4SXin Li if (encoder.initEncoder(const_cast<uint8_t **>(&data), &size)) {
225*600f14f4SXin Li encoder.encodeFrames(data, size);
226*600f14f4SXin Li }
227*600f14f4SXin Li return 0;
228*600f14f4SXin Li }
229