stream_encoder.c 175 KB
Newer Older
1
/* libFLAC - Free Lossless Audio Codec library
2
3
 * Copyright (C) 2000-2009  Josh Coalson
 * Copyright (C) 2011-2013  Xiph.Org Foundation
Josh Coalson's avatar
Josh Coalson committed
4
 *
5
6
7
 * 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
8
 *
9
10
 * - 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
11
 *
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 * - 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
31
32
 */

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

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

66

67
68
69
70
71
72
73
74
75
76
/* 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.
 */
77
#undef ENABLE_RICE_PARAMETER_SEARCH
78

79

Josh Coalson's avatar
Josh Coalson committed
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
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;

98
99
100
101
102
103
104
105
106
107
108
109
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_[] = {
110
111
	{ false, false,  0, 0, false, false, false, 0, 3, 0 },
	{ true , true ,  0, 0, false, false, false, 0, 3, 0 },
112
	{ true , false,  0, 0, false, false, false, 0, 3, 0 },
113
114
115
116
	{ 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 },
117
118
	{ true , false,  8, 0, false, false, true , 0, 6, 0 },
	{ true , false, 12, 0, false, false, true , 0, 6, 0 }
119
120
121
};


122
123
124
125
126
127
/***********************************************************************
 *
 * Private class method prototypes
 *
 ***********************************************************************/

128
129
static void set_defaults_(FLAC__StreamEncoder *encoder);
static void free_(FLAC__StreamEncoder *encoder);
130
static FLAC__bool resize_buffers_(FLAC__StreamEncoder *encoder, unsigned new_blocksize);
131
132
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);
133
static void update_metadata_(const FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
134
#if FLAC__HAS_OGG
135
static void update_ogg_metadata_(FLAC__StreamEncoder *encoder);
Josh Coalson's avatar
Josh Coalson committed
136
#endif
137
static FLAC__bool process_frame_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block, FLAC__bool is_last_block);
138
static FLAC__bool process_subframes_(FLAC__StreamEncoder *encoder, FLAC__bool is_fractional_block);
Josh Coalson's avatar
Josh Coalson committed
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155

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,
156
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
157
158
	unsigned subframe_bps,
	const FLAC__Subframe *subframe,
159
	FLAC__BitWriter *frame
Josh Coalson's avatar
Josh Coalson committed
160
161
162
);

static unsigned evaluate_constant_subframe_(
163
	FLAC__StreamEncoder *encoder,
Josh Coalson's avatar
Josh Coalson committed
164
	const FLAC__int32 signal,
165
	unsigned blocksize,
Josh Coalson's avatar
Josh Coalson committed
166
167
168
169
170
171
172
173
174
175
176
177
178
179
	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,
180
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
181
182
183
184
185
186
187
188
	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
);

189
#ifndef FLAC__INTEGER_ONLY_LIBRARY
Josh Coalson's avatar
Josh Coalson committed
190
191
192
193
194
195
196
197
198
199
200
201
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,
202
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
203
204
205
206
207
208
209
	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
);
210
#endif
Josh Coalson's avatar
Josh Coalson committed
211
212

static unsigned evaluate_verbatim_subframe_(
213
	FLAC__StreamEncoder *encoder,
Josh Coalson's avatar
Josh Coalson committed
214
215
216
217
218
219
220
221
222
223
224
225
226
227
	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,
228
	unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
229
230
	unsigned min_partition_order,
	unsigned max_partition_order,
231
	unsigned bps,
Josh Coalson's avatar
Josh Coalson committed
232
233
	FLAC__bool do_escape_coding,
	unsigned rice_parameter_search_dist,
234
	FLAC__EntropyCodingMethod *best_ecm
Josh Coalson's avatar
Josh Coalson committed
235
236
237
);

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

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_(
257
#ifdef EXACT_RICE_BITS_CALCULATION
Josh Coalson's avatar
Josh Coalson committed
258
	const FLAC__int32 residual[],
259
#endif
Josh Coalson's avatar
Josh Coalson committed
260
261
262
263
264
	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,
265
	const unsigned rice_parameter_limit,
Josh Coalson's avatar
Josh Coalson committed
266
267
268
269
270
271
272
	const unsigned rice_parameter_search_dist,
	const unsigned partition_order,
	const FLAC__bool search_for_escapes,
	FLAC__EntropyCodingMethod_PartitionedRiceContents *partitioned_rice_contents,
	unsigned *bits
);

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

Josh Coalson's avatar
Josh Coalson committed
275
/* verify-related routines: */
Josh Coalson's avatar
Josh Coalson committed
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
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
);

292
static FLAC__StreamDecoderReadStatus verify_read_callback_(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
293
294
295
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
296

297
static FLAC__StreamEncoderReadStatus file_read_callback_(const FLAC__StreamEncoder *encoder, FLAC__byte buffer[], size_t *bytes, void *client_data);
298
299
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);
300
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);
301
static FILE *get_binary_stdout_(void);
Josh Coalson's avatar
Josh Coalson committed
302

303
304
305
306
307
308
309
310

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

typedef struct FLAC__StreamEncoderPrivate {
311
	unsigned input_capacity;                          /* current size (in samples) of the signal and residual buffers */
Josh Coalson's avatar
Josh Coalson committed
312
313
	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) */
314
#ifndef FLAC__INTEGER_ONLY_LIBRARY
315
316
	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) */
317
	FLAC__real *window[FLAC__MAX_APODIZATION_FUNCTIONS]; /* the pre-computed floating-point window for each apodization function */
318
	FLAC__real *windowed_signal;                      /* the integer_signal[] * current window[] */
319
#endif
320
321
	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
322
323
	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
324
325
326
327
	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];
328
329
330
331
	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];
332
	unsigned best_subframe[FLAC__MAX_CHANNELS];       /* index (0 or 1) into 2nd dimension of the above workspaces */
Josh Coalson's avatar
Josh Coalson committed
333
	unsigned best_subframe_mid_side[2];
334
	unsigned best_subframe_bits[FLAC__MAX_CHANNELS];  /* size in bits of the best subframe for each channel */
Josh Coalson's avatar
Josh Coalson committed
335
	unsigned best_subframe_bits_mid_side[2];
336
	FLAC__uint64 *abs_residual_partition_sums;        /* workspace where the sum of abs(candidate residual) for each partition is stored */
337
	unsigned *raw_bits_per_partition;                 /* workspace where the sum of silog2(candidate residual) for each partition is stored */
338
	FLAC__BitWriter *frame;                           /* the current frame being worked on */
339
340
	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 */
341
	FLAC__ChannelAssignment last_channel_assignment;
342
343
	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
344
345
	unsigned current_sample_number;
	unsigned current_frame_number;
346
	FLAC__MD5Context md5context;
347
	FLAC__CPUInfo cpuinfo;
348
	void (*local_precompute_partition_info_sums)(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[], unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps);
349
#ifndef FLAC__INTEGER_ONLY_LIBRARY
350
	unsigned (*local_fixed_compute_best_predictor)(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
351
352
353
354
#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
355
	void (*local_lpc_compute_autocorrelation)(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
356
357
358
	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[]);
359
#endif
360
361
362
	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 */
363
364
365
	FLAC__bool disable_constant_subframes;
	FLAC__bool disable_fixed_subframes;
	FLAC__bool disable_verbatim_subframes;
366
367
368
369
#if FLAC__HAS_OGG
	FLAC__bool is_ogg;
#endif
	FLAC__StreamEncoderReadCallback read_callback; /* currently only needed for Ogg FLAC */
370
371
	FLAC__StreamEncoderSeekCallback seek_callback;
	FLAC__StreamEncoderTellCallback tell_callback;
Josh Coalson's avatar
Josh Coalson committed
372
373
	FLAC__StreamEncoderWriteCallback write_callback;
	FLAC__StreamEncoderMetadataCallback metadata_callback;
374
	FLAC__StreamEncoderProgressCallback progress_callback;
Josh Coalson's avatar
Josh Coalson committed
375
	void *client_data;
376
377
378
379
380
381
	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;
382
	/* unaligned (original) pointers to allocated data */
Josh Coalson's avatar
Josh Coalson committed
383
384
	FLAC__int32 *integer_signal_unaligned[FLAC__MAX_CHANNELS];
	FLAC__int32 *integer_signal_mid_side_unaligned[2];
385
#ifndef FLAC__INTEGER_ONLY_LIBRARY
386
387
	FLAC__real *real_signal_unaligned[FLAC__MAX_CHANNELS]; /* (@@@ currently unused) */
	FLAC__real *real_signal_mid_side_unaligned[2]; /* (@@@ currently unused) */
388
389
	FLAC__real *window_unaligned[FLAC__MAX_APODIZATION_FUNCTIONS];
	FLAC__real *windowed_signal_unaligned;
390
#endif
Josh Coalson's avatar
Josh Coalson committed
391
392
	FLAC__int32 *residual_workspace_unaligned[FLAC__MAX_CHANNELS][2];
	FLAC__int32 *residual_workspace_mid_side_unaligned[2][2];
393
	FLAC__uint64 *abs_residual_partition_sums_unaligned;
394
	unsigned *raw_bits_per_partition_unaligned;
395
396
397
398
	/*
	 * These fields have been moved here from private function local
	 * declarations merely to save stack space during encoding.
	 */
399
#ifndef FLAC__INTEGER_ONLY_LIBRARY
400
	FLAC__real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER]; /* from process_subframe_() */
401
#endif
402
	FLAC__EntropyCodingMethod_PartitionedRiceContents partitioned_rice_contents_extra[2]; /* from find_best_partition_order_() */
Josh Coalson's avatar
Josh Coalson committed
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
	/*
	 * 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;
421
	FLAC__bool is_being_deleted; /* if true, call to ..._finish() from ..._delete() will not call the callbacks */
422
} FLAC__StreamEncoderPrivate;
Josh Coalson's avatar
Josh Coalson committed
423

424
425
426
427
428
429
/***********************************************************************
 *
 * Public static class data
 *
 ***********************************************************************/

430
FLAC_API const char * const FLAC__StreamEncoderStateString[] = {
431
	"FLAC__STREAM_ENCODER_OK",
432
	"FLAC__STREAM_ENCODER_UNINITIALIZED",
433
	"FLAC__STREAM_ENCODER_OGG_ERROR",
Josh Coalson's avatar
Josh Coalson committed
434
435
	"FLAC__STREAM_ENCODER_VERIFY_DECODER_ERROR",
	"FLAC__STREAM_ENCODER_VERIFY_MISMATCH_IN_AUDIO_DATA",
436
437
	"FLAC__STREAM_ENCODER_CLIENT_ERROR",
	"FLAC__STREAM_ENCODER_IO_ERROR",
438
	"FLAC__STREAM_ENCODER_FRAMING_ERROR",
439
440
441
442
443
444
	"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",
445
	"FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER",
446
447
448
449
450
451
452
453
454
455
456
	"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
457
458
};

459
FLAC_API const char * const FLAC__StreamEncoderReadStatusString[] = {
460
461
462
463
464
465
	"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"
};

466
FLAC_API const char * const FLAC__StreamEncoderWriteStatusString[] = {
467
468
	"FLAC__STREAM_ENCODER_WRITE_STATUS_OK",
	"FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR"
Josh Coalson's avatar
Josh Coalson committed
469
470
};

471
472
473
474
475
476
477
478
479
480
481
482
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"
};

483
484
485
486
487
488
489
490
491
492
493
494
495
/* 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;

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

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

508
	encoder = calloc(1, sizeof(FLAC__StreamEncoder));
509
510
	if(encoder == 0) {
		return 0;
511
	}
Josh Coalson's avatar
Josh Coalson committed
512

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

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

526
	encoder->private_->frame = FLAC__bitwriter_new();
527
528
529
530
531
532
	if(encoder->private_->frame == 0) {
		free(encoder->private_);
		free(encoder->protected_);
		free(encoder);
		return 0;
	}
533

534
535
	encoder->private_->file = 0;

536
	set_defaults_(encoder);
537

538
	encoder->private_->is_being_deleted = false;
539
540
541
542
543
544
545
546
547
548

	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++) {
549
550
		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];
551
552
	}
	for(i = 0; i < 2; i++) {
553
554
		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];
555
556
557
	}

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
558
559
		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]);
560
561
	}
	for(i = 0; i < 2; i++) {
562
563
		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]);
564
565
	}
	for(i = 0; i < 2; i++)
566
		FLAC__format_entropy_coding_method_partitioned_rice_contents_init(&encoder->private_->partitioned_rice_contents_extra[i]);
567

568
	encoder->protected_->state = FLAC__STREAM_ENCODER_UNINITIALIZED;
569

Josh Coalson's avatar
Josh Coalson committed
570
571
572
	return encoder;
}

573
FLAC_API void FLAC__stream_encoder_delete(FLAC__StreamEncoder *encoder)
Josh Coalson's avatar
Josh Coalson committed
574
{
575
576
	unsigned i;

577
578
579
	if (encoder == NULL)
		return ;

580
581
582
	FLAC__ASSERT(0 != encoder->protected_);
	FLAC__ASSERT(0 != encoder->private_);
	FLAC__ASSERT(0 != encoder->private_->frame);
583

584
585
	encoder->private_->is_being_deleted = true;

586
	(void)FLAC__stream_encoder_finish(encoder);
587

588
	if(0 != encoder->private_->verify.decoder)
Josh Coalson's avatar
Josh Coalson committed
589
		FLAC__stream_decoder_delete(encoder->private_->verify.decoder);
590
591

	for(i = 0; i < FLAC__MAX_CHANNELS; i++) {
592
593
		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]);
594
595
	}
	for(i = 0; i < 2; i++) {
596
597
		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]);
598
599
	}
	for(i = 0; i < 2; i++)
600
		FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(&encoder->private_->partitioned_rice_contents_extra[i]);
601

602
	FLAC__bitwriter_delete(encoder->private_->frame);
603
604
	free(encoder->private_);
	free(encoder->protected_);
Josh Coalson's avatar
Josh Coalson committed
605
606
607
	free(encoder);
}

608
609
610
611
612
613
/***********************************************************************
 *
 * Public class methods
 *
 ***********************************************************************/

614
615
616
617
618
619
620
621
622
623
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
624
625
{
	unsigned i;
626
	FLAC__bool metadata_has_seektable, metadata_has_vorbis_comment, metadata_picture_has_type1, metadata_picture_has_type2;
Josh Coalson's avatar
Josh Coalson committed
627

628
	FLAC__ASSERT(0 != encoder);
Josh Coalson's avatar
Josh Coalson committed
629

630
	if(encoder->protected_->state != FLAC__STREAM_ENCODER_UNINITIALIZED)
631
		return FLAC__STREAM_ENCODER_INIT_STATUS_ALREADY_INITIALIZED;
632

633
#if !FLAC__HAS_OGG
634
635
636
637
	if(is_ogg)
		return FLAC__STREAM_ENCODER_INIT_STATUS_UNSUPPORTED_CONTAINER;
#endif

638
639
	if(0 == write_callback || (seek_callback && 0 == tell_callback))
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_CALLBACKS;
Josh Coalson's avatar
Josh Coalson committed
640

641
	if(encoder->protected_->channels == 0 || encoder->protected_->channels > FLAC__MAX_CHANNELS)
642
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_NUMBER_OF_CHANNELS;
Josh Coalson's avatar
Josh Coalson committed
643

644
645
646
647
648
649
	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;
650

651
	if(encoder->protected_->bits_per_sample >= 32)
652
		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
653

654
	if(encoder->protected_->bits_per_sample < FLAC__MIN_BITS_PER_SAMPLE || encoder->protected_->bits_per_sample > FLAC__REFERENCE_CODEC_MAX_BITS_PER_SAMPLE)
655
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BITS_PER_SAMPLE;
Josh Coalson's avatar
Josh Coalson committed
656

657
	if(!FLAC__format_sample_rate_is_valid(encoder->protected_->sample_rate))
658
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_SAMPLE_RATE;
Josh Coalson's avatar
Josh Coalson committed
659

660
661
662
663
	if(encoder->protected_->blocksize == 0) {
		if(encoder->protected_->max_lpc_order == 0)
			encoder->protected_->blocksize = 1152;
		else
664
			encoder->protected_->blocksize = 4096;
665
666
	}

667
	if(encoder->protected_->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->protected_->blocksize > FLAC__MAX_BLOCK_SIZE)
668
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_BLOCK_SIZE;
Josh Coalson's avatar
Josh Coalson committed
669

670
	if(encoder->protected_->max_lpc_order > FLAC__MAX_LPC_ORDER)
671
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_MAX_LPC_ORDER;
672

673
	if(encoder->protected_->blocksize < encoder->protected_->max_lpc_order)
674
		return FLAC__STREAM_ENCODER_INIT_STATUS_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
675

676
677
	if(encoder->protected_->qlp_coeff_precision == 0) {
		if(encoder->protected_->bits_per_sample < 16) {
Josh Coalson's avatar
Josh Coalson committed
678
679
			/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
			/* @@@ until then we'll make a guess */
680
			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
681
		}
682
683
684
685
686
687
688
689
690
691
692
693
694
		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
695
			else
696
				encoder->protected_->qlp_coeff_precision = 13;
Josh Coalson's avatar
Josh Coalson committed
697
698
		}
		else {
699
700
701
702
703
704
			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
705
		}
706
		FLAC__ASSERT(encoder->protected_->qlp_coeff_precision <= FLAC__MAX_QLP_COEFF_PRECISION);
Josh Coalson's avatar
Josh Coalson committed
707
	}
708
	else if(encoder->protected_->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->protected_->qlp_coeff_precision > FLAC__MAX_QLP_COEFF_PRECISION)
709
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_QLP_COEFF_PRECISION;
Josh Coalson's avatar
Josh Coalson committed
710

711
	if(encoder->protected_->streamable_subset) {
712
		if(!FLAC__format_blocksize_is_subset(encoder->protected_->blocksize, encoder->protected_->sample_rate))
713
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
714
		if(!FLAC__format_sample_rate_is_subset(encoder->protected_->sample_rate))
715
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
716
717
718
719
720
721
722
		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
		)
723
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
724
		if(encoder->protected_->max_residual_partition_order > FLAC__SUBSET_MAX_RICE_PARTITION_ORDER)
725
			return FLAC__STREAM_ENCODER_INIT_STATUS_NOT_STREAMABLE;
726
727
728
729
730
731
732
733
734
		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
735
736
	}

737
738
739
740
	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
741

742
743
744
#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
745
746
747
748
749
750
		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];
751
752
753
754
755
756
757
758
				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
759
760
761
762
		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;
763
764
765
766
767
				break; /* take only the first one */
			}
		}
	}

768
769
	/* validate metadata */
	if(0 == encoder->protected_->metadata && encoder->protected_->num_metadata_blocks > 0)
770
		return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
771
772
	metadata_has_seektable = false;
	metadata_has_vorbis_comment = false;
773
774
	metadata_picture_has_type1 = false;
	metadata_picture_has_type2 = false;
775
	for(i = 0; i < encoder->protected_->num_metadata_blocks; i++) {
776
777
		const FLAC__StreamMetadata *m = encoder->protected_->metadata[i];
		if(m->type == FLAC__METADATA_TYPE_STREAMINFO)
778
			return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
779
		else if(m->type == FLAC__METADATA_TYPE_SEEKTABLE) {
Josh Coalson's avatar
Josh Coalson committed
780
			if(metadata_has_seektable) /* only one is allowed */
781
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
782
			metadata_has_seektable = true;
783
			if(!FLAC__format_seektable_is_legal(&m->data.seek_table))
784
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
785
		}
786
		else if(m->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
Josh Coalson's avatar
Josh Coalson committed
787
			if(metadata_has_vorbis_comment) /* only one is allowed */
788
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
Josh Coalson's avatar
Josh Coalson committed
789
790
			metadata_has_vorbis_comment = true;
		}
791
792
		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))
793
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
794
		}
795
796
		else if(m->type == FLAC__METADATA_TYPE_PICTURE) {
			if(!FLAC__format_picture_is_legal(&m->data.picture, /*violation=*/0))
797
				return FLAC__STREAM_ENCODER_INIT_STATUS_INVALID_METADATA;
798
799
800
801
802
803
			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(
804
					m->data.picture.type == FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD &&
805
806
807
808
809
810
811
812
813
814
815
816
817
					(
						(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;
			}
818
		}
819
820
	}

821
822
823
	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;
824
#ifndef FLAC__INTEGER_ONLY_LIBRARY
825
		encoder->private_->real_signal_unaligned[i] = encoder->private_->real_signal[i] = 0;
826
#endif
Josh Coalson's avatar
Josh Coalson committed
827
828
	}
	for(i = 0; i < 2; i++) {
829
		encoder->private_->integer_signal_mid_side_unaligned[i] = encoder->private_->integer_signal_mid_side[i] = 0;
830
#ifndef FLAC__INTEGER_ONLY_LIBRARY
831
		encoder->private_->real_signal_mid_side_unaligned[i] = encoder->private_->real_signal_mid_side[i] = 0;
832
#endif
Josh Coalson's avatar
Josh Coalson committed
833
	}
834
835
836
837
838
#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
839
840
841
842
	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
843
844
	}
	for(i = 0; i < 2; i++) {
845
846
847
		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
848
	}
849
850
	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;
851
852
853
854
855
856
857
858
859
860
861
#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
862
863
864
865
866
867
868
	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);
869
	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? */
870
	encoder->private_->use_wide_by_partition = (false); /*@@@ need to set this */
871

872
873
874
	/*
	 * get the CPU info and set the function pointers
	 */
875
	FLAC__cpu_info(&encoder->private_->cpuinfo);
876
	/* first default to the non-asm routines */
877
#ifndef FLAC__INTEGER_ONLY_LIBRARY
878
	encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation;
879
#endif
880
	encoder->private_->local_precompute_partition_info_sums = precompute_partition_info_sums_;
881
	encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor;
882
#ifndef FLAC__INTEGER_ONLY_LIBRARY
883
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients;
884
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide;
885
	encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients;
886
#endif
887
	/* now override with asm where appropriate */
888
889
#ifndef FLAC__INTEGER_ONLY_LIBRARY
# ifndef FLAC__NO_ASM
890
	if(encoder->private_->cpuinfo.use_asm) {
891
#  ifdef FLAC__CPU_IA32
892
		FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_IA32);
893
#   ifdef FLAC__HAS_NASM
894
		encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_asm_ia32;
895
		if(encoder->private_->cpuinfo.ia32.sse) {
896
897
898
899
900
901
			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;
902
903
			else if(encoder->protected_->max_lpc_order < 16)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_16;
904
			else
905
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
906
		}
907
		else if(encoder->private_->cpuinfo.ia32._3dnow)
908
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32_3dnow;
909
		else
910
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_asm_ia32;
911
		if(encoder->private_->cpuinfo.ia32.mmx) {
912
913
			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;
914
915
		}
		else {
916
917
			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;
918
		}
919
		if(encoder->private_->cpuinfo.ia32.mmx && encoder->private_->cpuinfo.ia32.cmov)
920
921
			encoder->private_->local_fixed_compute_best_predictor = FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov;
#   endif /* FLAC__HAS_NASM */
922
#   ifdef FLAC__HAS_X86INTRIN
923
924
925
926
927
928
929
930
931
932
933
934
#    if defined FLAC__SSE_SUPPORTED && !defined FLAC__HAS_NASM
		if(encoder->private_->cpuinfo.ia32.sse) {
			if(encoder->protected_->max_lpc_order < 4)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4;
			else if(encoder->protected_->max_lpc_order < 8)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8;
			else if(encoder->protected_->max_lpc_order < 12)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12;
			else if(encoder->protected_->max_lpc_order < 16)
				encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16;
		}
#    endif
935
#    ifdef FLAC__SSE2_SUPPORTED
936
937
938
939
		if(encoder->private_->cpuinfo.ia32.sse2) {
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2;
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2;
		}
940
941
#    endif
#    ifdef FLAC__SSE4_1_SUPPORTED
942
943
944
945
		if(encoder->private_->cpuinfo.ia32.sse41)
			encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_64bit = FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_sse41;
#    endif
#   endif /* FLAC__HAS_X86INTRIN */
946
947
948
#  elif defined FLAC__CPU_X86_64
		FLAC__ASSERT(encoder->private_->cpuinfo.type == FLAC__CPUINFO_TYPE_X86_64);
#   ifdef FLAC__HAS_X86INTRIN
949
#    ifdef FLAC__SSE_SUPPORTED
950
951
952
953
954
955
956
957
		if(encoder->protected_->max_lpc_order < 4)
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4;
		else if(encoder->protected_->max_lpc_order < 8)
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8;
		else if(encoder->protected_->max_lpc_order < 12)
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12;
		else if(encoder->protected_->max_lpc_order < 16)
			encoder->private_->local_lpc_compute_autocorrelation = FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16;
958
959
#    endif
#    ifdef FLAC__SSE2_SUPPORTED
960
		/* encoder->private_->local_lpc_compute_residual_from_qlp_coefficients = FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2; // OPT: not faster than C; TODO: more tests on different CPUs */
961
		encoder->private_->local_lpc_compute_residual_from_qlp_coefficients_16bit = FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2;
962
#    endif
963
964
#   endif /* FLAC__HAS_X86INTRIN */
#  endif /* FLAC__CPU_... */
965
	}
966
967
# endif /* !FLAC__NO_ASM */
#endif /* !FLAC__INTEGER_ONLY_LIBRARY */
968
969
970
#if !defined FLAC__NO_ASM && defined FLAC__HAS_X86INTRIN
	if(encoder->private_->cpuinfo.use_asm) {
# if defined FLAC__CPU_IA32
971
972
#  ifdef FLAC__SSE2_SUPPORTED
#   ifdef FLAC__SSSE3_SUPPORTED
973
		if(encoder->private_->cpuinfo.ia32.ssse3)