stream_encoder.c 170 KB
Newer Older
1
/* libFLAC - Free Lossless Audio Codec library
Josh Coalson's avatar
Josh Coalson committed
2
 * Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008,2009  Josh Coalson
Josh Coalson's avatar
Josh Coalson committed
3
 *
4
5
6
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
Josh Coalson's avatar
Josh Coalson committed
7
 *
8
9
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
Josh Coalson's avatar
Josh Coalson committed
10
 *
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of the Xiph.org Foundation nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Josh Coalson's avatar
Josh Coalson committed
30
31
 */

Josh Coalson's avatar
Josh Coalson committed
32
33
34
35
#if HAVE_CONFIG_H
#  include <config.h>
#endif

36
#include <limits.h>
Josh Coalson's avatar
Josh Coalson committed
37
38
39
#include <stdio.h>
#include <stdlib.h> /* for malloc() */
#include <string.h> /* for memcpy() */
40
#include <sys/types.h> /* for off_t */
41
#include "FLAC/assert.h"
Josh Coalson's avatar
Josh Coalson committed
42
#include "FLAC/stream_decoder.h"
43
#include "protected/stream_encoder.h"
44
#include "private/bitwriter.h"
45
#include "private/bitmath.h"
46
#include "private/crc.h"
47
#include "private/cpu.h"
Josh Coalson's avatar
Josh Coalson committed
48
#include "private/fixed.h"
49
#include "private/format.h"
Josh Coalson's avatar
Josh Coalson committed
50
#include "private/lpc.h"
Josh Coalson's avatar
Josh Coalson committed
51
#include "private/md5.h"
52
#include "private/memory.h"
53
#include "private/macros.h"
54
#if FLAC__HAS_OGG
55
#include "private/ogg_helper.h"
56
#include "private/ogg_mapping.h"
57
#endif
58
#include "private/stream_encoder_framing.h"
59
#include "private/window.h"
60
61
62
#include "share/alloc.h"
#include "share/compat.h"
#include "share/private.h"
Josh Coalson's avatar
Josh Coalson committed
63

64

65
66
67
68
69
70
71
72
73
74
/* Exact Rice codeword length calculation is off by default.  The simple
 * (and fast) estimation (of how many bits a residual value will be
 * encoded with) in this encoder is very good, almost always yielding
 * compression within 0.1% of exact calculation.
 */
#undef EXACT_RICE_BITS_CALCULATION
/* Rice parameter searching is off by default.  The simple (and fast)
 * parameter estimation in this encoder is very good, almost always
 * yielding compression within 0.1% of the optimal parameters.
 */
75
#undef ENABLE_RICE_PARAMETER_SEARCH
76

77

Josh Coalson's avatar
Josh Coalson committed
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
typedef struct {
	FLAC__int32 *data[FLAC__MAX_CHANNELS];
	unsigned size; /* of each data[] in samples */
	unsigned tail;
} verify_input_fifo;

typedef struct {
	const FLAC__byte *data;
	unsigned capacity;
	unsigned bytes;
} verify_output;

typedef enum {
	ENCODER_IN_MAGIC = 0,
	ENCODER_IN_METADATA = 1,
	ENCODER_IN_AUDIO = 2
} EncoderStateHint;

96
97
98
99
100
101
102
103
104
105
106
107
static struct CompressionLevels {
	FLAC__bool do_mid_side_stereo;
	FLAC__bool loose_mid_side_stereo;
	unsigned max_lpc_order;
	unsigned qlp_coeff_precision;
	FLAC__bool do_qlp_coeff_prec_search;
	FLAC__bool do_escape_coding;
	FLAC__bool do_exhaustive_model_search;
	unsigned min_residual_partition_order;
	unsigned max_residual_partition_order;
	unsigned rice_parameter_search_dist;
} compression_levels_[] = {
108
109
	{ false, false,  0, 0, false, false, false, 0, 3, 0 },
	{ true , true ,  0, 0, false, false, false, 0, 3, 0 },
110
	{ true , false,  0, 0, false, false, false, 0, 3, 0 },
111
112
113
114
	{ false, false,  6, 0, false, false, false, 0, 4, 0 },
	{ true , true ,  8, 0, false, false, false, 0, 4, 0 },
	{ true , false,  8, 0, false, false, false, 0, 5, 0 },
	{ true , false,  8, 0, false, false, false, 0, 6, 0 },
115
116
	{ true , false,  8, 0, false, false, true , 0, 6, 0 },
	{ true , false, 12, 0, false, false, true , 0, 6, 0 }
117
118
119
};


120
121
122
123
124
125
/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

126
127
static void set_defaults_(FLAC__StreamEncoder *encoder);
static void free_(FLAC__StreamEncoder *encoder);
128
static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize);
129
130
static FLAC__bool write_bitbuffer_(FLAC__StreamEncoder *encoder, unsigned samples, FLAC__bool is_last_block);
static FLAC__StreamEncoderWriteStatus write_frame_(FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, FLAC__bool is_last_block);
131
static void update_metadata_(const FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
132
#if FLAC__HAS_OGG
133
static void update_ogg_metadata_(FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
134
#endif
135
static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block);
136
static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block);
Josh Coalson's avatar
Josh Coalson committed
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153

static FLAC__bool process_subframe_(
	FLAC__StreamEncoder *encoder,
	unsigned min_partition_order,
	unsigned max_partition_order,
	const FLAC__FrameHeader *frame_header,
	unsigned subframe_bps,
	const FLAC__int32 integer_signal[],
	FLAC__Subframe *subframe[2],
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents[2],
	FLAC__int32 *residual[2],
	unsigned *best_subframe,
	unsigned *best_bits
);

static FLAC__bool add_subframe_(
	FLAC__StreamEncoder *encoder,
154
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
155
156
	unsigned subframe_bps,
	const FLAC__Subframe *subframe,
157
	FLAC__BitWriter *frame
Josh Coalson's avatar
Josh Coalson committed
158
159
160
);

static unsigned evaluate_constant_subframe_(
161
	FLAC__StreamEncoder *encoder,
Josh Coalson's avatar
Josh Coalson committed
162
	const FLAC__int32 signal,
163
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
164
165
166
167
168
169
170
171
172
173
174
175
176
177
	unsigned subframe_bps,
	FLAC__Subframe *subframe
);

static unsigned evaluate_fixed_subframe_(
	FLAC__StreamEncoder *encoder,
	const FLAC__int32 signal[],
	FLAC__int32 residual[],
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned raw_bits_per_partition[],
	unsigned blocksize,
	unsigned subframe_bps,
	unsigned order,
	unsigned rice_parameter,
178
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
179
180
181
182
183
184
185
186
	unsigned min_partition_order,
	unsigned max_partition_order,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__Subframe *subframe,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
);

187
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
188
189
190
191
192
193
194
195
196
197
198
199
static unsigned evaluate_lpc_subframe_(
	FLAC__StreamEncoder *encoder,
	const FLAC__int32 signal[],
	FLAC__int32 residual[],
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned raw_bits_per_partition[],
	const FLAC__real lp_coeff[],
	unsigned blocksize,
	unsigned subframe_bps,
	unsigned order,
	unsigned qlp_coeff_precision,
	unsigned rice_parameter,
200
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
201
202
203
204
205
206
207
	unsigned min_partition_order,
	unsigned max_partition_order,
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
	FLAC__Subframe *subframe,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents
);
208
#endif
Josh Coalson's avatar
Josh Coalson committed
209
210

static unsigned evaluate_verbatim_subframe_(
211
	FLAC__StreamEncoder *encoder,
Josh Coalson's avatar
Josh Coalson committed
212
213
214
215
216
217
218
219
220
221
222
223
224
225
	const FLAC__int32 signal[],
	unsigned blocksize,
	unsigned subframe_bps,
	FLAC__Subframe *subframe
);

static unsigned find_best_partition_order_(
	struct FLAC__StreamEncoderPrivate *private_,
	const FLAC__int32 residual[],
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned raw_bits_per_partition[],
	unsigned residual_samples,
	unsigned predictor_order,
	unsigned rice_parameter,
226
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
227
228
	unsigned min_partition_order,
	unsigned max_partition_order,
229
	unsigned bps,
Josh Coalson's avatar
Josh Coalson committed
230
231
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
232
	FLAC__EntropyCodingMethod *best_ecm
Josh Coalson's avatar
Josh Coalson committed
233
234
235
);

static void precompute_partition_info_sums_(
236
	const FLAC__int32 residual[],
Josh Coalson's avatar
Josh Coalson committed
237
238
239
240
	FLAC__uint64 abs_residual_partition_sums[],
	unsigned residual_samples,
	unsigned predictor_order,
	unsigned min_partition_order,
241
242
	unsigned max_partition_order,
	unsigned bps
Josh Coalson's avatar
Josh Coalson committed
243
244
245
246
247
248
249
250
251
252
253
254
);

static void precompute_partition_info_escapes_(
	const FLAC__int32 residual[],
	unsigned raw_bits_per_partition[],
	unsigned residual_samples,
	unsigned predictor_order,
	unsigned min_partition_order,
	unsigned max_partition_order
);

static FLAC__bool set_partitioned_rice_(
255
#ifdef EXACT_RICE_BITS_CALCULATION
Josh Coalson's avatar
Josh Coalson committed
256
	const FLAC__int32 residual[],
257
#endif
Josh Coalson's avatar
Josh Coalson committed
258
259
260
261
262
	const FLAC__uint64 abs_residual_partition_sums[],
	const unsigned raw_bits_per_partition[],
	const unsigned residual_samples,
	const unsigned predictor_order,
	const unsigned suggested_rice_parameter,
263
	const unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
264
265
266
267
268
269
270
	const unsigned rice_parameter_search_dist,
	const unsigned partition_order,
	const FLAC__bool search_for_escapes,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
	unsigned *bits
);

271
static unsigned get_wasted_bits_(FLAC__int32 signal[], unsigned samples);
Josh Coalson's avatar
Josh Coalson committed
272

Josh Coalson's avatar
Josh Coalson committed
273
/* verify-related routines: */
Josh Coalson's avatar
Josh Coalson committed
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
static void append_to_verify_fifo_(
	verify_input_fifo *fifo,
	const FLAC__int32 * const input[],
	unsigned input_offset,
	unsigned channels,
	unsigned wide_samples
);

static void append_to_verify_fifo_interleaved_(
	verify_input_fifo *fifo,
	const FLAC__int32 input[],
	unsigned input_offset,
	unsigned channels,
	unsigned wide_samples
);

290
static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
291
292
293
static FLAC__StreamDecoderWriteStatus verify_write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
static void verify_metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data);
static void verify_error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
Josh Coalson's avatar
Josh Coalson committed
294

295
static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
296
297
static FLAC__StreamEncoderSeekStatus file_seek_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data);
static FLAC__StreamEncoderTellStatus file_tell_callback_(const FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data);
298
static FLAC__StreamEncoderWriteStatus file_write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame, void *client_data);
299
static FILE *get_binary_stdout_(void);
Josh Coalson's avatar
Josh Coalson committed
300

301
302
303
304
305
306
307
308

/***********************************************************************
 *
 * Private class data
 *
 ***********************************************************************/

typedef struct FLAC__StreamEncoderPrivate {
309
	unsigned input_capacity;                          /* current size (in samples) of the signal and residual buffers */
Josh Coalson's avatar
Josh Coalson committed
310
311
	FLAC__int32 *integer_signal[FLAC__MAX_CHANNELS];  /* the integer version of the input signal */
	FLAC__int32 *integer_signal_mid_side[2];          /* the integer version of the mid-side input signal (stereo only) */
312
#ifndef FLAC__INTEGER_ONLY_LIBRARY
313
314
	FLAC__real *real_signal[FLAC__MAX_CHANNELS];      /* (@@@ currently unused) the floating-point version of the input signal */
	FLAC__real *real_signal_mid_side[2];              /* (@@@ currently unused) the floating-point version of the mid-side input signal (stereo only) */
315
	FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
316
	FLAC__real *windowed_signal;                      /* the integer_signal[] * current window[] */
317
#endif
318
319
	unsigned subframe_bps[FLAC__MAX_CHANNELS];        /* the effective bits per sample of the input signal (stream bps - wasted bits) */
	unsigned subframe_bps_mid_side[2];                /* the effective bits per sample of the mid-side input signal (stream bps - wasted bits + 0/1) */
Josh Coalson's avatar
Josh Coalson committed
320
321
	FLAC__int32 *residual_workspace[FLAC__MAX_CHANNELS][2]; /* each channel has a candidate and best workspace where the subframe residual signals will be stored */
	FLAC__int32 *residual_workspace_mid_side[2][2];
Josh Coalson's avatar
Josh Coalson committed
322
323
324
325
	FLAC__Subframe subframe_workspace[FLAC__MAX_CHANNELS][2];
	FLAC__Subframe subframe_workspace_mid_side[2][2];
	FLAC__Subframe *subframe_workspace_ptr[FLAC__MAX_CHANNELS][2];
	FLAC__Subframe *subframe_workspace_ptr_mid_side[2][2];
326
327
328
329
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace[FLAC__MAX_CHANNELS][2];
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_workspace_mid_side[FLAC__MAX_CHANNELS][2];
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr[FLAC__MAX_CHANNELS][2];
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents_workspace_ptr_mid_side[FLAC__MAX_CHANNELS][2];
330
	unsigned best_subframe[FLAC__MAX_CHANNELS];       /* index (0 or 1) into 2nd dimension of the above workspaces */
Josh Coalson's avatar
Josh Coalson committed
331
	unsigned best_subframe_mid_side[2];
332
	unsigned best_subframe_bits[FLAC__MAX_CHANNELS];  /* size in bits of the best subframe for each channel */
Josh Coalson's avatar
Josh Coalson committed
333
	unsigned best_subframe_bits_mid_side[2];
334
	FLAC__uint64 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
335
	unsigned *raw_bits_per_partition;                 /* workspace where the sum of silog2(candidate residual) for each partition is stored */
336
	FLAC__BitWriter *frame;                           /* the current frame being worked on */
337
338
	unsigned loose_mid_side_stereo_frames;            /* rounded number of frames the encoder will use before trying both independent and mid/side frames again */
	unsigned loose_mid_side_stereo_frame_count;       /* number of frames using the current channel assignment */
339
	FLAC__ChannelAssignment last_channel_assignment;
340
341
	FLAC__StreamMetadata streaminfo;                  /* scratchpad for STREAMINFO as it is built */
	FLAC__StreamMetadata_SeekTable *seek_table;       /* pointer into encoder->protected_->metadata_ where the seek table is */
Josh Coalson's avatar
Josh Coalson committed
342
343
	unsigned current_sample_number;
	unsigned current_frame_number;
344
	FLAC__MD5Context md5context;
345
	FLAC__CPUInfo cpuinfo;
346
#ifndef FLAC__INTEGER_ONLY_LIBRARY
347
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
348
349
350
351
#else
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
#endif
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
352
	void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
353
354
355
	void (*local_lpc_compute_residual_from_qlp_coefficients)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
	void (*local_lpc_compute_residual_from_qlp_coefficients_64bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
	void (*local_lpc_compute_residual_from_qlp_coefficients_16bit)(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
356
#endif
357
358
359
	FLAC__bool use_wide_by_block;          /* use slow 64-bit versions of some functions because of the block size */
	FLAC__bool use_wide_by_partition;      /* use slow 64-bit versions of some functions because of the min partition order and blocksize */
	FLAC__bool use_wide_by_order;          /* use slow 64-bit versions of some functions because of the lpc order */
360
361
362
	FLAC__bool disable_constant_subframes;
	FLAC__bool disable_fixed_subframes;
	FLAC__bool disable_verbatim_subframes;
363
364
365
366
#if FLAC__HAS_OGG
	FLAC__bool is_ogg;
#endif
	FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */
367
368
	FLAC__StreamEncoderSeekCallback seek_callback;
	FLAC__StreamEncoderTellCallback tell_callback;
Josh Coalson's avatar
Josh Coalson committed
369
370
	FLAC__StreamEncoderWriteCallback write_callback;
	FLAC__StreamEncoderMetadataCallback metadata_callback;
371
	FLAC__StreamEncoderProgressCallback progress_callback;
Josh Coalson's avatar
Josh Coalson committed
372
	void *client_data;
373
374
375
376
377
378
	unsigned first_seekpoint_to_check;
	FILE *file;                            /* only used when encoding to a file */
	FLAC__uint64 bytes_written;
	FLAC__uint64 samples_written;
	unsigned frames_written;
	unsigned total_frames_estimate;
379
	/* unaligned (original) pointers to allocated data */
Josh Coalson's avatar
Josh Coalson committed
380
381
	FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__int32 *integer_signal_mid_side_unaligned[2];
382
#ifndef FLAC__INTEGER_ONLY_LIBRARY
383
384
	FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) */
	FLAC__real *real_signal_mid_side_unaligned[2]; /* (@@@ currently unused) */
385
386
	FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
	FLAC__real *windowed_signal_unaligned;
387
#endif
Josh Coalson's avatar
Josh Coalson committed
388
389
	FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
	FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
390
	FLAC__uint64 *abs_residual_partition_sums_unaligned;
391
	unsigned *raw_bits_per_partition_unaligned;
392
393
394
395
	/*
	 * These fields have been moved here from private function local
	 * declarations merely to save stack space during encoding.
	 */
396
#ifndef FLAC__INTEGER_ONLY_LIBRARY
397
	FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
398
#endif
399
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalson's avatar
Josh Coalson committed
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
	/*
	 * The data for the verify section
	 */
	struct {
		FLAC__StreamDecoder *decoder;
		EncoderStateHint state_hint;
		FLAC__bool needs_magic_hack;
		verify_input_fifo input_fifo;
		verify_output output;
		struct {
			FLAC__uint64 absolute_sample;
			unsigned frame_number;
			unsigned channel;
			unsigned sample;
			FLAC__int32 expected;
			FLAC__int32 got;
		} error_stats;
	} verify;
418
	FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
419
} FLAC__StreamEncoderPrivate;
Josh Coalson's avatar
Josh Coalson committed
420

421
422
423
424
425
426
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/

427
FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
428
	"FLAC__STREAM_ENCODER_OK",
429
	"FLAC__STREAM_ENCODER_UNINITIALIZED",
430
	"FLAC__STREAM_ENCODER_OGG_ERROR",
Josh Coalson's avatar
Josh Coalson committed
431
432
	"FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
	"FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
433
434
	"FLAC__STREAM_ENCODER_CLIENT_ERROR",
	"FLAC__STREAM_ENCODER_IO_ERROR",
435
	"FLAC__STREAM_ENCODER_FRAMING_ERROR",
436
437
438
439
440
441
	"FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR"
};

FLAC_API const char * const FLAC__StreamEncoderInitStatusString[] = {
	"FLAC__STREAM_ENCODER_INIT_STATUS_OK",
	"FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR",
442
	"FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
443
444
445
446
447
448
449
450
451
452
453
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION",
	"FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER",
	"FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE",
	"FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA",
	"FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED"
Josh Coalson's avatar
Josh Coalson committed
454
455
};

456
FLAC_API const char * const FLAC__StreamEncoderReadStatusString[] = {
457
458
459
460
461
462
	"FLAC__STREAM_ENCODER_READ_STATUS_CONTINUE",
	"FLAC__STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
	"FLAC__STREAM_ENCODER_READ_STATUS_ABORT",
	"FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED"
};

463
FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
464
465
	"FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
	"FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalson's avatar
Josh Coalson committed
466
467
};

468
469
470
471
472
473
474
475
476
477
478
479
FLAC_API const char * const FLAC__StreamEncoderSeekStatusString[] = {
	"FLAC__STREAM_ENCODER_SEEK_STATUS_OK",
	"FLAC__STREAM_ENCODER_SEEK_STATUS_ERROR",
	"FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED"
};

FLAC_API const char * const FLAC__StreamEncoderTellStatusString[] = {
	"FLAC__STREAM_ENCODER_TELL_STATUS_OK",
	"FLAC__STREAM_ENCODER_TELL_STATUS_ERROR",
	"FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED"
};

480
481
482
483
484
485
486
487
488
489
490
491
492
/* Number of samples that will be overread to watch for end of stream.  By
 * 'overread', we mean that the FLAC__stream_encoder_process*() calls will
 * always try to read blocksize+1 samples before encoding a block, so that
 * even if the stream has a total sample count that is an integral multiple
 * of the blocksize, we will still notice when we are encoding the last
 * block.  This is needed, for example, to correctly set the end-of-stream
 * marker in Ogg FLAC.
 *
 * WATCHOUT: some parts of the code assert that OVERREAD_ == 1 and there's
 * not really any reason to change it.
 */
static const unsigned OVERREAD_ = 1;

493
494
495
496
/***********************************************************************
 *
 * Class constructor/destructor
 *
Josh Coalson's avatar
Josh Coalson committed
497
 */
498
FLAC_API FLAC__StreamEncoder *FLAC__stream_encoder_new(void)
Josh Coalson's avatar
Josh Coalson committed
499
{
500
	FLAC__StreamEncoder *encoder;
501
	unsigned i;
Josh Coalson's avatar
Josh Coalson committed
502

503
	FLAC__ASSERT(sizeof(int) >= 4); /* we want to die right away if this is not true */
Josh Coalson's avatar
Josh Coalson committed
504

505
	encoder = calloc(1, sizeof(FLAC__StreamEncoder));
506
507
	if(encoder == 0) {
		return 0;
508
	}
Josh Coalson's avatar
Josh Coalson committed
509

510
	encoder->protected_ = calloc(1, sizeof(FLAC__StreamEncoderProtected));
511
	if(encoder->protected_ == 0) {
512
513
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
514
	}
Josh Coalson's avatar
Josh Coalson committed
515

516
	encoder->private_ = calloc(1, sizeof(FLAC__StreamEncoderPrivate));
517
518
	if(encoder->private_ == 0) {
		free(encoder->protected_);
519
520
		free(encoder);
		return 0;
Josh Coalson's avatar
Josh Coalson committed
521
	}
Josh Coalson's avatar
Josh Coalson committed
522

523
	encoder->private_->frame = FLAC__bitwriter_new();
524
525
526
527
528
529
	if(encoder->private_->frame == 0) {
		free(encoder->private_);
		free(encoder->protected_);
		free(encoder);
		return 0;
	}
530

531
532
	encoder->private_->file = 0;

533
	set_defaults_(encoder);
534

535
	encoder->private_->is_being_deleted = false;
536
537
538
539
540
541
542
543
544
545

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
		encoder->private_->subframe_workspace_ptr[i][0] = &encoder->private_->subframe_workspace[i][0];
		encoder->private_->subframe_workspace_ptr[i][1] = &encoder->private_->subframe_workspace[i][1];
	}
	for(i = 0; i < 2; i++) {
		encoder->private_->subframe_workspace_ptr_mid_side[i][0] = &encoder->private_->subframe_workspace_mid_side[i][0];
		encoder->private_->subframe_workspace_ptr_mid_side[i][1] = &encoder->private_->subframe_workspace_mid_side[i][1];
	}
	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
546
547
		encoder->private_->partitioned_rice_contents_workspace_ptr[i][0] = &encoder->private_->partitioned_rice_contents_workspace[i][0];
		encoder->private_->partitioned_rice_contents_workspace_ptr[i][1] = &encoder->private_->partitioned_rice_contents_workspace[i][1];
548
549
	}
	for(i = 0; i < 2; i++) {
550
551
		encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][0] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0];
		encoder->private_->partitioned_rice_contents_workspace_ptr_mid_side[i][1] = &encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1];
552
553
554
	}

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
555
556
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
557
558
	}
	for(i = 0; i < 2; i++) {
559
560
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]);
561
562
	}
	for(i = 0; i < 2; i++)
563
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
564

565
	encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
566

Josh Coalson's avatar
Josh Coalson committed
567
568
569
	return encoder;
}

570
FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalson's avatar
Josh Coalson committed
571
{
572
573
	unsigned i;

574
575
576
	if (encoder == NULL)
		return ;

577
578
579
	FLAC__ASSERT(0 != encoder->protected_);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->private_->frame);
580

581
582
	encoder->private_->is_being_deleted = true;

583
	(void)FLAC__stream_encoder_finish(encoder);
584

585
	if(0 != encoder->private_->verify.decoder)
Josh Coalson's avatar
Josh Coalson committed
586
		FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
587
588

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
589
590
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace[i][1]);
591
592
	}
	for(i = 0; i < 2; i++) {
593
594
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][0]);
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_workspace_mid_side[i][1]);
595
596
	}
	for(i = 0; i < 2; i++)
597
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
598

599
	FLAC__bitwriter_delete(encoder->private_->frame);
600
601
	free(encoder->private_);
	free(encoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
602
603
604
	free(encoder);
}

605
606
607
608
609
610
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

611
612
613
614
615
616
617
618
619
620
static FLAC__StreamEncoderInitStatus init_stream_internal_(
	FLAC__StreamEncoder *encoder,
	FLAC__StreamEncoderReadCallback read_callback,
	FLAC__StreamEncoderWriteCallback write_callback,
	FLAC__StreamEncoderSeekCallback seek_callback,
	FLAC__StreamEncoderTellCallback tell_callback,
	FLAC__StreamEncoderMetadataCallback metadata_callback,
	void *client_data,
	FLAC__bool is_ogg
)
Josh Coalson's avatar
Josh Coalson committed
621
622
{
	unsigned i;
623
	FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
Josh Coalson's avatar
Josh Coalson committed
624

625
	FLAC__ASSERT(0 != encoder);
Josh Coalson's avatar
Josh Coalson committed
626

627
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
628
		return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
629

630
#if !FLAC__HAS_OGG
631
632
633
634
	if(is_ogg)
		return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
#endif

635
636
	if(0 == write_callback || (seek_callback && 0 == tell_callback))
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
Josh Coalson's avatar
Josh Coalson committed
637

638
	if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
639
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson's avatar
Josh Coalson committed
640

641
642
643
644
645
646
	if(encoder->protected_->channels != 2) {
		encoder->protected_->do_mid_side_stereo = false;
		encoder->protected_->loose_mid_side_stereo = false;
	}
	else if(!encoder->protected_->do_mid_side_stereo)
		encoder->protected_->loose_mid_side_stereo = false;
647

648
	if(encoder->protected_->bits_per_sample >= 32)
649
		encoder->protected_->do_mid_side_stereo = false; /* since we currenty do 32-bit math, the side channel would have 33 bps and overflow */
Josh Coalson's avatar
Josh Coalson committed
650

651
	if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
652
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
Josh Coalson's avatar
Josh Coalson committed
653

654
	if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
655
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
Josh Coalson's avatar
Josh Coalson committed
656

657
658
659
660
	if(encoder->protected_->blocksize == 0) {
		if(encoder->protected_->max_lpc_order == 0)
			encoder->protected_->blocksize = 1152;
		else
661
			encoder->protected_->blocksize = 4096;
662
663
	}

664
	if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
665
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
Josh Coalson's avatar
Josh Coalson committed
666

667
	if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
668
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
669

670
	if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
671
		return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
672

673
674
	if(encoder->protected_->qlp_coeff_precision == 0) {
		if(encoder->protected_->bits_per_sample < 16) {
Josh Coalson's avatar
Josh Coalson committed
675
676
			/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
			/* @@@ until then we'll make a guess */
677
			encoder->protected_->qlp_coeff_precision = flac_max(FLAC__MIN_QLP_COEFF_PRECISION, 2 + encoder->protected_->bits_per_sample / 2);
Josh Coalson's avatar
Josh Coalson committed
678
		}
679
680
681
682
683
684
685
686
687
688
689
690
691
		else if(encoder->protected_->bits_per_sample == 16) {
			if(encoder->protected_->blocksize <= 192)
				encoder->protected_->qlp_coeff_precision = 7;
			else if(encoder->protected_->blocksize <= 384)
				encoder->protected_->qlp_coeff_precision = 8;
			else if(encoder->protected_->blocksize <= 576)
				encoder->protected_->qlp_coeff_precision = 9;
			else if(encoder->protected_->blocksize <= 1152)
				encoder->protected_->qlp_coeff_precision = 10;
			else if(encoder->protected_->blocksize <= 2304)
				encoder->protected_->qlp_coeff_precision = 11;
			else if(encoder->protected_->blocksize <= 4608)
				encoder->protected_->qlp_coeff_precision = 12;
Josh Coalson's avatar
Josh Coalson committed
692
			else
693
				encoder->protected_->qlp_coeff_precision = 13;
Josh Coalson's avatar
Josh Coalson committed
694
695
		}
		else {
696
697
698
699
700
701
			if(encoder->protected_->blocksize <= 384)
				encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-2;
			else if(encoder->protected_->blocksize <= 1152)
				encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION-1;
			else
				encoder->protected_->qlp_coeff_precision = FLAC__MAX_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
702
		}
703
		FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalson's avatar
Josh Coalson committed
704
	}
705
	else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
706
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
707

708
	if(encoder->protected_->streamable_subset) {
709
		if(!FLAC__format_blocksize_is_subset(encoder->protected_->blocksize, encoder->protected_->sample_rate))
710
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
711
		if(!FLAC__format_sample_rate_is_subset(encoder->protected_->sample_rate))
712
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
713
714
715
716
717
718
719
		if(
			encoder->protected_->bits_per_sample != 8 &&
			encoder->protected_->bits_per_sample != 12 &&
			encoder->protected_->bits_per_sample != 16 &&
			encoder->protected_->bits_per_sample != 20 &&
			encoder->protected_->bits_per_sample != 24
		)
720
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
721
		if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
722
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
723
724
725
726
727
728
729
730
731
		if(
			encoder->protected_->sample_rate <= 48000 &&
			(
				encoder->protected_->blocksize > FLAC__SUBSET_MAX_BLOCK_SIZE_48000HZ ||
				encoder->protected_->max_lpc_order > FLAC__SUBSET_MAX_LPC_ORDER_48000HZ
			)
		) {
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
		}
Josh Coalson's avatar
Josh Coalson committed
732
733
	}

734
735
736
737
	if(encoder->protected_->max_residual_partition_order >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
		encoder->protected_->max_residual_partition_order = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
	if(encoder->protected_->min_residual_partition_order >= encoder->protected_->max_residual_partition_order)
		encoder->protected_->min_residual_partition_order = encoder->protected_->max_residual_partition_order;
Josh Coalson's avatar
Josh Coalson committed
738

739
740
741
#if FLAC__HAS_OGG
	/* reorder metadata if necessary to ensure that any VORBIS_COMMENT is the first, according to the mapping spec */
	if(is_ogg && 0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 1) {
Erik de Castro Lopo's avatar
Erik de Castro Lopo committed
742
743
744
745
746
747
		unsigned i1;
		for(i1 = 1; i1 < encoder->protected_->num_metadata_blocks; i1++) {
			if(0 != encoder->protected_->metadata[i1] && encoder->protected_->metadata[i1]->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
				FLAC__StreamMetadata *vc = encoder->protected_->metadata[i1];
				for( ; i1 > 0; i1--)
					encoder->protected_->metadata[i1] = encoder->protected_->metadata[i1-1];
748
749
750
751
752
753
754
755
				encoder->protected_->metadata[0] = vc;
				break;
			}
		}
	}
#endif
	/* keep track of any SEEKTABLE block */
	if(0 != encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0) {
Erik de Castro Lopo's avatar
Erik de Castro Lopo committed
756
757
758
759
		unsigned i2;
		for(i2 = 0; i2 < encoder->protected_->num_metadata_blocks; i2++) {
			if(0 != encoder->protected_->metadata[i2] && encoder->protected_->metadata[i2]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
				encoder->private_->seek_table = &encoder->protected_->metadata[i2]->data.seek_table;
760
761
762
763
764
				break; /* take only the first one */
			}
		}
	}

765
766
	/* validate metadata */
	if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
767
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
768
769
	metadata_has_seektable = false;
	metadata_has_vorbis_comment = false;
770
771
	metadata_picture_has_type1 = false;
	metadata_picture_has_type2 = false;
772
	for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
773
774
		const FLAC__StreamMetadata *m = encoder->protected_->metadata[i];
		if(m->type == FLAC__METADATA_TYPE_STREAMINFO)
775
			return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
776
		else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
777
			if(metadata_has_seektable) /* only one is allowed */
778
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
779
			metadata_has_seektable = true;
780
			if(!FLAC__format_seektable_is_legal(&m->data.seek_table))
781
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
782
		}
783
		else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
Josh Coalson's avatar
Josh Coalson committed
784
			if(metadata_has_vorbis_comment) /* only one is allowed */
785
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
786
787
			metadata_has_vorbis_comment = true;
		}
788
789
		else if(m->type == FLAC__METADATA_TYPE_CUESHEET) {
			if(!FLAC__format_cuesheet_is_legal(&m->data.cue_sheet, m->data.cue_sheet.is_cd, /*violation=*/0))
790
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
791
		}
792
793
		else if(m->type == FLAC__METADATA_TYPE_PICTURE) {
			if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0))
794
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
795
796
797
798
799
800
			if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD) {
				if(metadata_picture_has_type1) /* there should only be 1 per stream */
					return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
				metadata_picture_has_type1 = true;
				/* standard icon must be 32x32 pixel PNG */
				if(
801
					m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD &&
802
803
804
805
806
807
808
809
810
811
812
813
814
					(
						(strcmp(m->data.picture.mime_type, "image/png") && strcmp(m->data.picture.mime_type, "-->")) ||
						m->data.picture.width != 32 ||
						m->data.picture.height != 32
					)
				)
					return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
			}
			else if(m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON) {
				if(metadata_picture_has_type2) /* there should only be 1 per stream */
					return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
				metadata_picture_has_type2 = true;
			}
815
		}
816
817
	}

818
819
820
	encoder->private_->input_capacity = 0;
	for(i = 0; i < encoder->protected_->channels; i++) {
		encoder->private_->integer_signal_unaligned[i] = encoder->private_->integer_signal[i] = 0;
821
#ifndef FLAC__INTEGER_ONLY_LIBRARY
822
		encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
823
#endif
Josh Coalson's avatar
Josh Coalson committed
824
825
	}
	for(i = 0; i < 2; i++) {
826
		encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
827
#ifndef FLAC__INTEGER_ONLY_LIBRARY
828
		encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
829
#endif
Josh Coalson's avatar
Josh Coalson committed
830
	}
831
832
833
834
835
#ifndef FLAC__INTEGER_ONLY_LIBRARY
	for(i = 0; i < encoder->protected_->num_apodizations; i++)
		encoder->private_->window_unaligned[i] = encoder->private_->window[i] = 0;
	encoder->private_->windowed_signal_unaligned = encoder->private_->windowed_signal = 0;
#endif
836
837
838
839
	for(i = 0; i < encoder->protected_->channels; i++) {
		encoder->private_->residual_workspace_unaligned[i][0] = encoder->private_->residual_workspace[i][0] = 0;
		encoder->private_->residual_workspace_unaligned[i][1] = encoder->private_->residual_workspace[i][1] = 0;
		encoder->private_->best_subframe[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
840
841
	}
	for(i = 0; i < 2; i++) {
842
843
844
		encoder->private_->residual_workspace_mid_side_unaligned[i][0] = encoder->private_->residual_workspace_mid_side[i][0] = 0;
		encoder->private_->residual_workspace_mid_side_unaligned[i][1] = encoder->private_->residual_workspace_mid_side[i][1] = 0;
		encoder->private_->best_subframe_mid_side[i] = 0;
Josh Coalson's avatar
Josh Coalson committed
845
	}
846
847
	encoder->private_->abs_residual_partition_sums_unaligned = encoder->private_->abs_residual_partition_sums = 0;
	encoder->private_->raw_bits_per_partition_unaligned = encoder->private_->raw_bits_per_partition = 0;
848
849
850
851
852
853
854
855
856
857
858
#ifndef FLAC__INTEGER_ONLY_LIBRARY
	encoder->private_->loose_mid_side_stereo_frames = (unsigned)((FLAC__double)encoder->protected_->sample_rate * 0.4 / (FLAC__double)encoder->protected_->blocksize + 0.5);
#else
	/* 26214 is the approximate fixed-point equivalent to 0.4 (0.4 * 2^16) */
	/* sample rate can be up to 655350 Hz, and thus use 20 bits, so we do the multiply&divide by hand */
	FLAC__ASSERT(FLAC__MAX_SAMPLE_RATE <= 655350);
	FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535);
	FLAC__ASSERT(encoder->protected_->sample_rate <= 655350);
	FLAC__ASSERT(encoder->protected_->blocksize <= 65535);
	encoder->private_->loose_mid_side_stereo_frames = (unsigned)FLAC__fixedpoint_trunc((((FLAC__uint64)(encoder->protected_->sample_rate) * (FLAC__uint64)(26214)) << 16) / (encoder->protected_->blocksize<<16) + FLAC__FP_ONE_HALF);
#endif
859
860
861
862
863
864
865
	if(encoder->private_->loose_mid_side_stereo_frames == 0)
		encoder->private_->loose_mid_side_stereo_frames = 1;
	encoder->private_->loose_mid_side_stereo_frame_count = 0;
	encoder->private_->current_sample_number = 0;
	encoder->private_->current_frame_number = 0;

	encoder->private_->use_wide_by_block = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(encoder->protected_->blocksize)+1 > 30);
866
	encoder->private_->use_wide_by_order = (encoder->protected_->bits_per_sample + FLAC__bitmath_ilog2(flac_max(encoder->protected_->max_lpc_order, FLAC__MAX_FIXED_ORDER))+1 > 30); /*@@@ need to use this? */
867
	encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
868

869
870
871
	/*
	 * get the CPU info and set the function pointers
	 */
872
	FLAC__cpu_info(&encoder->private_->cpuinfo);
873
	/* first default to the non-asm routines */
874
#ifndef FLAC__INTEGER_ONLY_LIBRARY
875
	encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
876
#endif
877
	encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
878
#ifndef FLAC__INTEGER_ONLY_LIBRARY
879
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
880
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
881
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
882
#endif
883
	/* now override with asm where appropriate */
884
885
#ifndef FLAC__INTEGER_ONLY_LIBRARY
# ifndef FLAC__NO_ASM
886
	if(encoder->private_->cpuinfo.use_asm) {
887
#  ifdef FLAC__CPU_IA32
888
		FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
889
#   ifdef FLAC__HAS_NASM
890
		if(encoder->private_->cpuinfo.data.ia32.sse) {
891
892
893
894
895
896
			if(encoder->protected_->max_lpc_order < 4)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4;
			else if(encoder->protected_->max_lpc_order < 8)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8;
			else if(encoder->protected_->max_lpc_order < 12)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12;
897
			else
898
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
899
		}
900
		else if(encoder->private_->cpuinfo.data.ia32._3dnow)
901
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
902
		else
903
904
905
906
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
		if(encoder->private_->cpuinfo.data.ia32.mmx) {
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx;
907
908
		}
		else {
909
910
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32;
911
		}
912
913
914
915
		if(encoder->private_->cpuinfo.data.ia32.mmx && encoder->private_->cpuinfo.data.ia32.cmov)
			encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
#   endif /* FLAC__HAS_NASM */
#  endif /* FLAC__CPU_IA32 */
916
	}
917
918
# endif /* !FLAC__NO_ASM */
#endif /* !FLAC__INTEGER_ONLY_LIBRARY */
919
	/* finally override based on wide-ness if necessary */
920
921
	if(encoder->private_->use_wide_by_block) {
		encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_wide;
922
	}
923

924
925
926
	/* set state to OK; from here on, errors are fatal and we'll override the state then */
	encoder->protected_->state = FLAC__STREAM_ENCODER_OK;

927
928
929
930
931
932
933
934
935
#if FLAC__HAS_OGG
	encoder->private_->is_ogg = is_ogg;
	if(is_ogg && !FLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect)) {
		encoder->protected_->state = FLAC__STREAM_ENCODER_OGG_ERROR;
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
	}
#endif

	encoder->private_->read_callback = read_callback;
936
937
938
939
940
941
	encoder->private_->write_callback = write_callback;
	encoder->private_->seek_callback = seek_callback;
	encoder->private_->tell_callback = tell_callback;
	encoder->private_->metadata_callback = metadata_callback;
	encoder->private_->client_data = client_data;

942
	if(!resize_buffers_(encoder, encoder->protected_->blocksize)) {
Josh Coalson's avatar
Josh Coalson committed
943
		/* the above function sets the state for us in case of an error */
944
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
Josh Coalson's avatar
Josh Coalson committed
945
	}
946

947
	if(!FLAC__bitwriter_init(encoder->private_->frame)) {
948
949
950
		encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
		return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
	}
Josh Coalson's avatar
Josh Coalson committed
951

Josh Coalson's avatar
Josh Coalson committed
952
953
954
955
956
957
958
959
	/*
	 * Set up the verify stuff if necessary
	 */
	if(encoder->protected_->verify) {
		/*
		 * First, set up the fifo which will hold the
		 * original signal to compare against
		 */
960
		encoder->private_->verify.input_fifo.size = encoder->protected_->blocksize+OVERREAD_;
Josh Coalson's avatar
Josh Coalson committed
961
		for(i = 0; i < encoder->protected_->channels; i++) {
962
			if(0 == (encoder->private_->verify.input_fifo.data[i] = safe_malloc_mul_2op_p(sizeof(FLAC__int32), /*times*/encoder->private_->verify.input_fifo.size))) {
963
964
965
				encoder->protected_->state = FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR;
				return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
			}
Josh Coalson's avatar
Josh Coalson committed
966
967
968
969
970
971
		}
		encoder->private_->verify.input_fifo.tail = 0;

		/*
		 * Now set up a stream decoder for verification
		 */
972
		if(0 == encoder->private_->verify.decoder) {
973
974
975
976
977
			encoder->private_->verify.decoder = FLAC__stream_decoder_new();
			if(0 == encoder->private_->verify.decoder) {
				encoder->protected_->state = FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR;
				return FLAC__STREAM_ENCODER_INIT_STATUS_ENCODER_ERROR;
			}
978
		}
Josh Coalson's avatar
Josh Coalson committed
979

980
981
982
983
		if(FLAC__stream_decoder_init_stream(encoder->private_->verify.decoder, verify_read_callback_, /*seek_callback=*/0, /*tell_callback=*/0, /*length_callback=*/0, /*eof_callback=*/0,