1*600f14f4SXin Li /* fuzzer_encoder_v2
2*600f14f4SXin Li * Copyright (C) 2022-2023 Xiph.Org Foundation
3*600f14f4SXin Li *
4*600f14f4SXin Li * Redistribution and use in source and binary forms, with or without
5*600f14f4SXin Li * modification, are permitted provided that the following conditions
6*600f14f4SXin Li * are met:
7*600f14f4SXin Li *
8*600f14f4SXin Li * - Redistributions of source code must retain the above copyright
9*600f14f4SXin Li * notice, this list of conditions and the following disclaimer.
10*600f14f4SXin Li *
11*600f14f4SXin Li * - Redistributions in binary form must reproduce the above copyright
12*600f14f4SXin Li * notice, this list of conditions and the following disclaimer in the
13*600f14f4SXin Li * documentation and/or other materials provided with the distribution.
14*600f14f4SXin Li *
15*600f14f4SXin Li * - Neither the name of the Xiph.org Foundation nor the names of its
16*600f14f4SXin Li * contributors may be used to endorse or promote products derived from
17*600f14f4SXin Li * this software without specific prior written permission.
18*600f14f4SXin Li *
19*600f14f4SXin Li * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20*600f14f4SXin Li * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21*600f14f4SXin Li * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22*600f14f4SXin Li * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23*600f14f4SXin Li * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24*600f14f4SXin Li * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25*600f14f4SXin Li * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26*600f14f4SXin Li * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27*600f14f4SXin Li * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28*600f14f4SXin Li * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29*600f14f4SXin Li * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*600f14f4SXin Li */
31*600f14f4SXin Li
32*600f14f4SXin Li #include <cstdlib>
33*600f14f4SXin Li #include <cstring> /* for memcpy */
34*600f14f4SXin Li #include "FLAC/stream_encoder.h"
35*600f14f4SXin Li #include "FLAC/metadata.h"
36*600f14f4SXin Li extern "C" {
37*600f14f4SXin Li #include "share/private.h"
38*600f14f4SXin Li }
39*600f14f4SXin Li #include "common.h"
40*600f14f4SXin Li
41*600f14f4SXin Li /* This C++ fuzzer uses the FLAC and not FLAC++ because the latter lacks a few
42*600f14f4SXin Li * hidden functions like FLAC__stream_encoder_disable_constant_subframes. It
43*600f14f4SXin Li * is still processed by a C++ compiler because that's what oss-fuzz expects */
44*600f14f4SXin Li
45*600f14f4SXin Li
write_callback(const FLAC__StreamEncoder * encoder,const FLAC__byte buffer[],size_t bytes,uint32_t samples,uint32_t current_frame,void * client_data)46*600f14f4SXin Li static FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, uint32_t samples, uint32_t current_frame, void *client_data)
47*600f14f4SXin Li {
48*600f14f4SXin Li (void)encoder, (void)buffer, (void)bytes, (void)samples, (void)current_frame, (void)client_data;
49*600f14f4SXin Li return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
50*600f14f4SXin Li }
51*600f14f4SXin Li
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)52*600f14f4SXin Li extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
53*600f14f4SXin Li {
54*600f14f4SXin Li FLAC__bool encoder_valid = true;
55*600f14f4SXin Li FLAC__StreamEncoder *encoder = 0;
56*600f14f4SXin Li FLAC__StreamEncoderState state;
57*600f14f4SXin Li FLAC__StreamMetadata *metadata[16] = {NULL};
58*600f14f4SXin Li unsigned num_metadata = 0;
59*600f14f4SXin Li FLAC__StreamMetadata_VorbisComment_Entry VorbisCommentField;
60*600f14f4SXin Li
61*600f14f4SXin Li unsigned sample_rate, channels, bps;
62*600f14f4SXin Li uint64_t samples_estimate, samples_in_input;
63*600f14f4SXin Li unsigned compression_level, input_data_width, blocksize, max_lpc_order, qlp_coeff_precision, min_residual_partition_order, max_residual_partition_order, metadata_mask, instruction_set_disable_mask;
64*600f14f4SXin Li FLAC__bool ogg, write_to_file, interleaved;
65*600f14f4SXin Li
66*600f14f4SXin Li FLAC__bool data_bools[24];
67*600f14f4SXin Li
68*600f14f4SXin Li /* Set alloc threshold. This check was added later and no spare config
69*600f14f4SXin Li * bytes were left, so we're reusing the sample rate as that of little
70*600f14f4SXin Li * consequence to the encoder and decoder except reading the frame header */
71*600f14f4SXin Li
72*600f14f4SXin Li if(size < 3)
73*600f14f4SXin Li return 0;
74*600f14f4SXin Li alloc_check_threshold = data[2];
75*600f14f4SXin Li alloc_check_counter = 0;
76*600f14f4SXin Li
77*600f14f4SXin Li /* allocate the encoder */
78*600f14f4SXin Li if((encoder = FLAC__stream_encoder_new()) == NULL) {
79*600f14f4SXin Li fprintf(stderr, "ERROR: allocating encoder\n");
80*600f14f4SXin Li return 1;
81*600f14f4SXin Li }
82*600f14f4SXin Li
83*600f14f4SXin Li /* Use first 20 byte for configuration */
84*600f14f4SXin Li if(size < 20){
85*600f14f4SXin Li FLAC__stream_encoder_delete(encoder);
86*600f14f4SXin Li return 0;
87*600f14f4SXin Li }
88*600f14f4SXin Li
89*600f14f4SXin Li /* First 3 byte for sample rate, 4th byte for channels, 5th byte for bps */
90*600f14f4SXin Li sample_rate = ((unsigned)data[0] << 16) + ((unsigned)data[1] << 8) + data[2];
91*600f14f4SXin Li channels = data[3];
92*600f14f4SXin Li bps = data[4];
93*600f14f4SXin Li
94*600f14f4SXin Li /* Number of samples estimate, format accepts 36-bit max */
95*600f14f4SXin Li samples_estimate = ((uint64_t)data[5] << 32) + ((unsigned)data[6] << 24) + ((unsigned)data[7] << 16) + ((unsigned)data[8] << 8) + data[9];
96*600f14f4SXin Li
97*600f14f4SXin Li compression_level = data[10]&0b1111;
98*600f14f4SXin Li input_data_width = 1 + (data[10]>>4)%4;
99*600f14f4SXin Li samples_in_input = (size-20)/input_data_width;
100*600f14f4SXin Li blocksize = ((unsigned)data[11] << 8) + (unsigned)data[12];
101*600f14f4SXin Li max_lpc_order = data[13];
102*600f14f4SXin Li qlp_coeff_precision = data[14];
103*600f14f4SXin Li min_residual_partition_order = data[15] & 0b1111;
104*600f14f4SXin Li max_residual_partition_order = data[15] & 0b11110000;
105*600f14f4SXin Li metadata_mask = data[16];
106*600f14f4SXin Li instruction_set_disable_mask = data[17];
107*600f14f4SXin Li
108*600f14f4SXin Li /* Get array of bools from configuration */
109*600f14f4SXin Li for(int i = 0; i < 16; i++)
110*600f14f4SXin Li data_bools[i] = data[18+i/8] & (1 << (i % 8));
111*600f14f4SXin Li
112*600f14f4SXin Li ogg = data_bools[0];
113*600f14f4SXin Li interleaved = data_bools[1];
114*600f14f4SXin Li write_to_file = data_bools[13];
115*600f14f4SXin Li
116*600f14f4SXin Li /* Set input and process parameters */
117*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_verify(encoder, data_bools[2]);
118*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_channels(encoder, channels);
119*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_bits_per_sample(encoder, bps);
120*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_sample_rate(encoder, sample_rate);
121*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_total_samples_estimate(encoder, samples_estimate);
122*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_disable_instruction_set(encoder, instruction_set_disable_mask);
123*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_limit_min_bitrate(encoder, data_bools[15]);
124*600f14f4SXin Li
125*600f14f4SXin Li /* Set compression related parameters */
126*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_compression_level(encoder, compression_level);
127*600f14f4SXin Li if(data_bools[3]){
128*600f14f4SXin Li /* Bias towards regular compression levels */
129*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_blocksize(encoder, blocksize);
130*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_max_lpc_order(encoder, max_lpc_order);
131*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_qlp_coeff_precision(encoder, qlp_coeff_precision);
132*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_min_residual_partition_order(encoder, min_residual_partition_order);
133*600f14f4SXin Li
134*600f14f4SXin Li /* With large inputs and expensive options enabled, the fuzzer can get *really* slow.
135*600f14f4SXin Li * Some combinations can make the fuzzer timeout (>60 seconds). However, while combining
136*600f14f4SXin Li * options makes the fuzzer slower, most options do not expose new code when combined.
137*600f14f4SXin Li * Therefore, combining slow options is disabled for large inputs. Any input containing
138*600f14f4SXin Li * more than 65536 * 2 samples (max blocksize, stereo) is considered large
139*600f14f4SXin Li */
140*600f14f4SXin Li if(samples_in_input < (2*65536)) {
141*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, data_bools[4]);
142*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, data_bools[5]);
143*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, data_bools[6]);
144*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, data_bools[7]);
145*600f14f4SXin Li /* Combining model search, precision search and a high residual partition order is especially
146*600f14f4SXin Li * expensive, so limit that even further. This high partition order can only be set on
147*600f14f4SXin Li * large blocksize and with streamable subset disabled */
148*600f14f4SXin Li if(samples_in_input < (2 * 4609) || data_bools[4] || !data_bools[7] || !data_bools[5] || max_residual_partition_order < 9 || blocksize < 4609)
149*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_max_residual_partition_order(encoder, max_residual_partition_order);
150*600f14f4SXin Li }
151*600f14f4SXin Li else {
152*600f14f4SXin Li if(!data_bools[4])
153*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_streamable_subset(encoder, false);
154*600f14f4SXin Li else if(data_bools[6])
155*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_escape_coding(encoder, true);
156*600f14f4SXin Li else if(data_bools[7])
157*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_exhaustive_model_search(encoder, true);
158*600f14f4SXin Li else if(data_bools[5])
159*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder, true);
160*600f14f4SXin Li }
161*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_do_mid_side_stereo(encoder, data_bools[8]);
162*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_set_loose_mid_side_stereo(encoder, data_bools[9]);
163*600f14f4SXin Li
164*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_disable_constant_subframes(encoder, data_bools[10]);
165*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_disable_fixed_subframes(encoder, data_bools[11]);
166*600f14f4SXin Li encoder_valid &= FLAC__stream_encoder_disable_verbatim_subframes(encoder, data_bools[12]);
167*600f14f4SXin Li }
168*600f14f4SXin Li
169*600f14f4SXin Li /* Disable alloc check if requested */
170*600f14f4SXin Li if(encoder_valid && data_bools[14])
171*600f14f4SXin Li alloc_check_threshold = INT32_MAX;
172*600f14f4SXin Li
173*600f14f4SXin Li /* add metadata */
174*600f14f4SXin Li if(encoder_valid && (metadata_mask & 1)) {
175*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_STREAMINFO)) == NULL)
176*600f14f4SXin Li encoder_valid = false;
177*600f14f4SXin Li else
178*600f14f4SXin Li num_metadata++;
179*600f14f4SXin Li }
180*600f14f4SXin Li if(encoder_valid && (metadata_mask & 2) && size > 21){
181*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL)
182*600f14f4SXin Li encoder_valid = false;
183*600f14f4SXin Li else {
184*600f14f4SXin Li metadata[num_metadata++]->length = (((unsigned)data[20]) << 8) + (unsigned)(data[21]);
185*600f14f4SXin Li }
186*600f14f4SXin Li }
187*600f14f4SXin Li if(encoder_valid && (metadata_mask & 4) && size > 20){
188*600f14f4SXin Li FLAC__byte * application_data = (FLAC__byte *)malloc(size-20);
189*600f14f4SXin Li if(0 != application_data && ((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_APPLICATION)) == NULL))
190*600f14f4SXin Li encoder_valid = false;
191*600f14f4SXin Li else {
192*600f14f4SXin Li memcpy(application_data,data+20,size-20);
193*600f14f4SXin Li FLAC__metadata_object_application_set_data(metadata[num_metadata++], application_data, size-20, 0);
194*600f14f4SXin Li }
195*600f14f4SXin Li }
196*600f14f4SXin Li if(encoder_valid && (metadata_mask & 8) && size > 25){
197*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_SEEKTABLE)) == NULL)
198*600f14f4SXin Li encoder_valid = false;
199*600f14f4SXin Li else {
200*600f14f4SXin Li unsigned seekpoint_spacing = ((unsigned)data[22] << 8) + data[23];
201*600f14f4SXin Li unsigned total_samples_for_seekpoints = ((unsigned)data[24] << 8) + data[25];
202*600f14f4SXin Li FLAC__metadata_object_seektable_template_append_spaced_points_by_samples(metadata[num_metadata++], seekpoint_spacing, total_samples_for_seekpoints);
203*600f14f4SXin Li }
204*600f14f4SXin Li }
205*600f14f4SXin Li if(encoder_valid && (metadata_mask & 16)){
206*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) != NULL) {
207*600f14f4SXin Li bool vorbiscomment_valid = true;
208*600f14f4SXin Li /* Append a vorbis comment */
209*600f14f4SXin Li if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Nothing to report"))
210*600f14f4SXin Li vorbiscomment_valid = false;
211*600f14f4SXin Li else {
212*600f14f4SXin Li if(FLAC__metadata_object_vorbiscomment_append_comment(metadata[num_metadata], VorbisCommentField, false)) {
213*600f14f4SXin Li
214*600f14f4SXin Li /* Insert a vorbis comment at the first index */
215*600f14f4SXin Li if(!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&VorbisCommentField, "COMMENTARY", "Still nothing to report "))
216*600f14f4SXin Li vorbiscomment_valid = false;
217*600f14f4SXin Li else
218*600f14f4SXin Li if(!FLAC__metadata_object_vorbiscomment_insert_comment(metadata[num_metadata], 0, VorbisCommentField, false)) {
219*600f14f4SXin Li free(VorbisCommentField.entry);
220*600f14f4SXin Li vorbiscomment_valid = false;
221*600f14f4SXin Li }
222*600f14f4SXin Li }
223*600f14f4SXin Li else {
224*600f14f4SXin Li free(VorbisCommentField.entry);
225*600f14f4SXin Li vorbiscomment_valid = false;
226*600f14f4SXin Li }
227*600f14f4SXin Li }
228*600f14f4SXin Li if(!vorbiscomment_valid) {
229*600f14f4SXin Li FLAC__metadata_object_delete(metadata[num_metadata]);
230*600f14f4SXin Li metadata[num_metadata] = 0;
231*600f14f4SXin Li }
232*600f14f4SXin Li else
233*600f14f4SXin Li num_metadata++;
234*600f14f4SXin Li }
235*600f14f4SXin Li }
236*600f14f4SXin Li if(encoder_valid && (metadata_mask & 32)){
237*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_CUESHEET)) != NULL) {
238*600f14f4SXin Li if(!FLAC__metadata_object_cuesheet_insert_blank_track(metadata[num_metadata],0)) {
239*600f14f4SXin Li FLAC__metadata_object_delete(metadata[num_metadata]);
240*600f14f4SXin Li metadata[num_metadata] = 0;
241*600f14f4SXin Li }
242*600f14f4SXin Li else {
243*600f14f4SXin Li if(!FLAC__metadata_object_cuesheet_track_insert_blank_index(metadata[num_metadata],0,0)) {
244*600f14f4SXin Li FLAC__metadata_object_delete(metadata[num_metadata]);
245*600f14f4SXin Li metadata[num_metadata] = 0;
246*600f14f4SXin Li }
247*600f14f4SXin Li else {
248*600f14f4SXin Li metadata[num_metadata]->data.cue_sheet.tracks[0].number = 1;
249*600f14f4SXin Li num_metadata++;
250*600f14f4SXin Li }
251*600f14f4SXin Li }
252*600f14f4SXin Li }
253*600f14f4SXin Li }
254*600f14f4SXin Li if(encoder_valid && (metadata_mask & 64)){
255*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PICTURE)) != NULL) {
256*600f14f4SXin Li num_metadata++;
257*600f14f4SXin Li }
258*600f14f4SXin Li }
259*600f14f4SXin Li if(encoder_valid && (metadata_mask & 128)){
260*600f14f4SXin Li if((metadata[num_metadata] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_UNDEFINED)) != NULL) {
261*600f14f4SXin Li metadata[num_metadata]->length = 24;
262*600f14f4SXin Li metadata[num_metadata]->data.unknown.data = (FLAC__byte *)calloc(24, 1);
263*600f14f4SXin Li num_metadata++;
264*600f14f4SXin Li }
265*600f14f4SXin Li }
266*600f14f4SXin Li
267*600f14f4SXin Li if(num_metadata && encoder_valid)
268*600f14f4SXin Li encoder_valid = FLAC__stream_encoder_set_metadata(encoder, metadata, num_metadata);
269*600f14f4SXin Li
270*600f14f4SXin Li /* initialize encoder */
271*600f14f4SXin Li if(encoder_valid) {
272*600f14f4SXin Li FLAC__StreamEncoderInitStatus init_status;
273*600f14f4SXin Li if(ogg)
274*600f14f4SXin Li if(write_to_file)
275*600f14f4SXin Li init_status = FLAC__stream_encoder_init_ogg_file(encoder, "/tmp/tmp.flac", NULL, NULL);
276*600f14f4SXin Li else
277*600f14f4SXin Li init_status = FLAC__stream_encoder_init_ogg_stream(encoder, NULL, write_callback, NULL, NULL, NULL, NULL);
278*600f14f4SXin Li else
279*600f14f4SXin Li if(write_to_file)
280*600f14f4SXin Li init_status = FLAC__stream_encoder_init_file(encoder, "/tmp/tmp.flac", NULL, NULL);
281*600f14f4SXin Li else
282*600f14f4SXin Li init_status = FLAC__stream_encoder_init_stream(encoder, write_callback, NULL, NULL, NULL, NULL);
283*600f14f4SXin Li if(init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
284*600f14f4SXin Li encoder_valid = false;
285*600f14f4SXin Li }
286*600f14f4SXin Li }
287*600f14f4SXin Li
288*600f14f4SXin Li
289*600f14f4SXin Li /* send samples to encoder */
290*600f14f4SXin Li if(encoder_valid && size > (input_data_width*channels+26)) {
291*600f14f4SXin Li unsigned samples = (size - 26)/input_data_width/channels;
292*600f14f4SXin Li const uint8_t * pcm_data = data + 26;
293*600f14f4SXin Li int32_t * data_as_int32 = (int32_t *)malloc(4*samples*channels);
294*600f14f4SXin Li if(0 != data_as_int32){
295*600f14f4SXin Li for(unsigned i = 0; i < samples*channels; i++)
296*600f14f4SXin Li if(input_data_width == 1)
297*600f14f4SXin Li data_as_int32[i] = (int32_t)pcm_data[i] - 0x80;
298*600f14f4SXin Li else if(input_data_width == 2)
299*600f14f4SXin Li data_as_int32[i] = (((int32_t)pcm_data[i*2] << 8) + pcm_data[i*2+1]) - 0x8000;
300*600f14f4SXin Li else if(input_data_width == 3)
301*600f14f4SXin Li data_as_int32[i] = (((int32_t)pcm_data[i*3] << 16) + ((int32_t)pcm_data[i*3+1] << 8) + pcm_data[i*3+2]) - 0x800000;
302*600f14f4SXin Li else if(input_data_width == 4)
303*600f14f4SXin Li data_as_int32[i] = (((int64_t)pcm_data[i*4] << 24) + ((int32_t)pcm_data[i*4+1] << 16) + ((int32_t)pcm_data[i*4+2] << 8) + pcm_data[i*4+3]) - 0x80000000;
304*600f14f4SXin Li
305*600f14f4SXin Li /* feed samples to encoder */
306*600f14f4SXin Li if(interleaved)
307*600f14f4SXin Li encoder_valid = FLAC__stream_encoder_process_interleaved(encoder, data_as_int32, samples);
308*600f14f4SXin Li else {
309*600f14f4SXin Li encoder_valid = FLAC__stream_encoder_process(encoder, (const int32_t*[]){data_as_int32,
310*600f14f4SXin Li data_as_int32+samples,
311*600f14f4SXin Li data_as_int32+samples*2,
312*600f14f4SXin Li data_as_int32+samples*3,
313*600f14f4SXin Li data_as_int32+samples*4, data_as_int32+samples*5, data_as_int32+samples*6, data_as_int32+samples*7}, samples);
314*600f14f4SXin Li }
315*600f14f4SXin Li free(data_as_int32);
316*600f14f4SXin Li }
317*600f14f4SXin Li else {
318*600f14f4SXin Li encoder_valid = false;
319*600f14f4SXin Li }
320*600f14f4SXin Li }
321*600f14f4SXin Li
322*600f14f4SXin Li state = FLAC__stream_encoder_get_state(encoder);
323*600f14f4SXin Li if(!(state == FLAC__STREAM_ENCODER_OK ||
324*600f14f4SXin Li state == FLAC__STREAM_ENCODER_UNINITIALIZED ||
325*600f14f4SXin Li state == FLAC__STREAM_ENCODER_CLIENT_ERROR ||
326*600f14f4SXin Li ((state == FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR ||
327*600f14f4SXin Li state == FLAC__STREAM_ENCODER_FRAMING_ERROR ||
328*600f14f4SXin Li (state == FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR &&
329*600f14f4SXin Li FLAC__stream_encoder_get_verify_decoder_state(encoder) == FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR)) &&
330*600f14f4SXin Li alloc_check_threshold < INT32_MAX))) {
331*600f14f4SXin Li fprintf(stderr,"-----\nERROR: stream encoder returned %s\n-----\n",FLAC__stream_encoder_get_resolved_state_string(encoder));
332*600f14f4SXin Li if(state == FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA) {
333*600f14f4SXin Li uint32_t frame_number, channel, sample_number;
334*600f14f4SXin Li FLAC__int32 expected, got;
335*600f14f4SXin Li FLAC__stream_encoder_get_verify_decoder_error_stats(encoder, NULL, &frame_number, &channel, &sample_number, &expected, &got);
336*600f14f4SXin Li fprintf(stderr,"Frame number %d\nChannel %d\n Sample number %d\nExpected value %d\nGot %d\n", frame_number, channel, sample_number, expected, got);
337*600f14f4SXin Li }
338*600f14f4SXin Li abort();
339*600f14f4SXin Li }
340*600f14f4SXin Li
341*600f14f4SXin Li FLAC__stream_encoder_finish(encoder);
342*600f14f4SXin Li
343*600f14f4SXin Li /* now that encoding is finished, the metadata can be freed */
344*600f14f4SXin Li for(unsigned i = 0; i < 16; i++)
345*600f14f4SXin Li if(0 != metadata[i])
346*600f14f4SXin Li FLAC__metadata_object_delete(metadata[i]);
347*600f14f4SXin Li
348*600f14f4SXin Li FLAC__stream_encoder_delete(encoder);
349*600f14f4SXin Li
350*600f14f4SXin Li return 0;
351*600f14f4SXin Li }
352*600f14f4SXin Li
353