019edfe1ffef15c7ef8348631d4e4cef7cfb5b83
[flac.git] / src / libOggFLAC / stream_encoder.c
1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2  * Copyright (C) 2002  Josh Coalson
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA  02111-1307, USA.
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h> /* for malloc() */
22 #include <string.h> /* for memcpy() */
23 #include "ogg/ogg.h"
24 #include "FLAC/assert.h"
25 #include "OggFLAC/stream_decoder.h"
26 #include "protected/stream_encoder.h"
27
28 /***********************************************************************
29  *
30  * Private class method prototypes
31  *
32  ***********************************************************************/
33
34 /* unpublished debug routines */
35 extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
36 extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
37 extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
38
39 static void set_defaults_(OggFLAC__StreamEncoder *encoder);
40 static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
41 static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
42
43
44 /***********************************************************************
45  *
46  * Private class data
47  *
48  ***********************************************************************/
49
50 typedef struct OggFLAC__StreamEncoderPrivate {
51         OggFLAC__StreamEncoderWriteCallback write_callback;
52         void *client_data;
53         FLAC__StreamEncoder *FLAC_stream_encoder;
54         /* internal vars (all the above are class settings) */
55         FLAC__bool is_first_packet;
56         FLAC__uint64 samples_written;
57         struct {
58                 ogg_stream_state stream_state;
59                 ogg_page page;
60         } ogg;
61 } OggFLAC__StreamEncoderPrivate;
62
63
64 /***********************************************************************
65  *
66  * Public static class data
67  *
68  ***********************************************************************/
69
70 const OggFLAC_API char * const OggFLAC__StreamEncoderStateString[] = {
71         "OggFLAC__STREAM_ENCODER_OK",
72         "OggFLAC__STREAM_ENCODER_OGG_ERROR",
73         "OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR",
74         "OggFLAC__STREAM_ENCODER_INVALID_CALLBACK",
75         "OggFLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
76         "OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED",
77         "OggFLAC__STREAM_ENCODER_UNINITIALIZED"
78 };
79
80
81 /***********************************************************************
82  *
83  * Class constructor/destructor
84  *
85  */
86 OggFLAC_API OggFLAC__StreamEncoder *OggFLAC__stream_encoder_new()
87 {
88         OggFLAC__StreamEncoder *encoder;
89
90         encoder = (OggFLAC__StreamEncoder*)malloc(sizeof(OggFLAC__StreamEncoder));
91         if(encoder == 0) {
92                 return 0;
93         }
94         memset(encoder, 0, sizeof(OggFLAC__StreamEncoder));
95
96         encoder->protected_ = (OggFLAC__StreamEncoderProtected*)malloc(sizeof(OggFLAC__StreamEncoderProtected));
97         if(encoder->protected_ == 0) {
98                 free(encoder);
99                 return 0;
100         }
101         memset(encoder->protected_, 0, sizeof(OggFLAC__StreamEncoderProtected));
102
103         encoder->private_ = (OggFLAC__StreamEncoderPrivate*)malloc(sizeof(OggFLAC__StreamEncoderPrivate));
104         if(encoder->private_ == 0) {
105                 free(encoder->protected_);
106                 free(encoder);
107                 return 0;
108         }
109         memset(encoder->private_, 0, sizeof(OggFLAC__StreamEncoderPrivate));
110
111         encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new();
112         if(0 == encoder->private_->FLAC_stream_encoder) {
113                 free(encoder->private_);
114                 free(encoder->protected_);
115                 free(encoder);
116                 return 0;
117         }
118
119         set_defaults_(encoder);
120
121         encoder->protected_->state = OggFLAC__STREAM_ENCODER_UNINITIALIZED;
122
123         return encoder;
124 }
125
126 OggFLAC_API void OggFLAC__stream_encoder_delete(OggFLAC__StreamEncoder *encoder)
127 {
128         FLAC__ASSERT(0 != encoder);
129         FLAC__ASSERT(0 != encoder->protected_);
130         FLAC__ASSERT(0 != encoder->private_);
131         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
132
133         (void)OggFLAC__stream_encoder_finish(encoder);
134
135         FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder);
136
137         free(encoder->private_);
138         free(encoder->protected_);
139         free(encoder);
140 }
141
142
143 /***********************************************************************
144  *
145  * Public class methods
146  *
147  ***********************************************************************/
148
149 OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_init(OggFLAC__StreamEncoder *encoder)
150 {
151         FLAC__ASSERT(0 != encoder);
152
153         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
154                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_ALREADY_INITIALIZED;
155
156         if(0 == encoder->private_->write_callback)
157                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_INVALID_CALLBACK;
158
159         if(ogg_stream_init(&encoder->private_->ogg.stream_state, encoder->protected_->serial_number) != 0)
160                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OGG_ERROR;
161
162         FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_);
163         FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_);
164         FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder);
165
166         if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK)
167                 return encoder->protected_->state = OggFLAC__STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
168
169         encoder->private_->is_first_packet = true;
170         encoder->private_->samples_written = 0;
171
172         return encoder->protected_->state = OggFLAC__STREAM_ENCODER_OK;
173 }
174
175 OggFLAC_API void OggFLAC__stream_encoder_finish(OggFLAC__StreamEncoder *encoder)
176 {
177         FLAC__ASSERT(0 != encoder);
178         FLAC__ASSERT(0 != encoder->private_);
179         FLAC__ASSERT(0 != encoder->protected_);
180
181         if(encoder->protected_->state == OggFLAC__STREAM_ENCODER_UNINITIALIZED)
182                 return;
183
184         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
185
186         FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder);
187
188         (void)ogg_stream_clear(&encoder->private_->ogg.stream_state);
189
190         set_defaults_(encoder);
191
192         encoder->protected_->state = OggFLAC__STREAM_ENCODER_UNINITIALIZED;
193 }
194
195 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_serial_number(OggFLAC__StreamEncoder *encoder, long value)
196 {
197         FLAC__ASSERT(0 != encoder);
198         FLAC__ASSERT(0 != encoder->private_);
199         FLAC__ASSERT(0 != encoder->protected_);
200         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
201         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
202                 return false;
203         encoder->protected_->serial_number = value;
204         return true;
205 }
206
207 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_verify(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
208 {
209         FLAC__ASSERT(0 != encoder);
210         FLAC__ASSERT(0 != encoder->private_);
211         FLAC__ASSERT(0 != encoder->protected_);
212         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
213         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
214                 return false;
215         return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value);
216 }
217
218 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_streamable_subset(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
219 {
220         FLAC__ASSERT(0 != encoder);
221         FLAC__ASSERT(0 != encoder->private_);
222         FLAC__ASSERT(0 != encoder->protected_);
223         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
224         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
225                 return false;
226         return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value);
227 }
228
229 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
230 {
231         FLAC__ASSERT(0 != encoder);
232         FLAC__ASSERT(0 != encoder->private_);
233         FLAC__ASSERT(0 != encoder->protected_);
234         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
235         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
236                 return false;
237         return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
238 }
239
240 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_loose_mid_side_stereo(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
241 {
242         FLAC__ASSERT(0 != encoder);
243         FLAC__ASSERT(0 != encoder->private_);
244         FLAC__ASSERT(0 != encoder->protected_);
245         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
246         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
247                 return false;
248         return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
249 }
250
251 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_channels(OggFLAC__StreamEncoder *encoder, unsigned value)
252 {
253         FLAC__ASSERT(0 != encoder);
254         FLAC__ASSERT(0 != encoder->private_);
255         FLAC__ASSERT(0 != encoder->protected_);
256         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
257         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
258                 return false;
259         return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value);
260 }
261
262 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_bits_per_sample(OggFLAC__StreamEncoder *encoder, unsigned value)
263 {
264         FLAC__ASSERT(0 != encoder);
265         FLAC__ASSERT(0 != encoder->private_);
266         FLAC__ASSERT(0 != encoder->protected_);
267         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
268         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
269                 return false;
270         return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value);
271 }
272
273 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_sample_rate(OggFLAC__StreamEncoder *encoder, unsigned value)
274 {
275         FLAC__ASSERT(0 != encoder);
276         FLAC__ASSERT(0 != encoder->private_);
277         FLAC__ASSERT(0 != encoder->protected_);
278         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
279         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
280                 return false;
281         return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value);
282 }
283
284 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_blocksize(OggFLAC__StreamEncoder *encoder, unsigned value)
285 {
286         FLAC__ASSERT(0 != encoder);
287         FLAC__ASSERT(0 != encoder->private_);
288         FLAC__ASSERT(0 != encoder->protected_);
289         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
290         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
291                 return false;
292         return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
293 }
294
295 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_lpc_order(OggFLAC__StreamEncoder *encoder, unsigned value)
296 {
297         FLAC__ASSERT(0 != encoder);
298         FLAC__ASSERT(0 != encoder->private_);
299         FLAC__ASSERT(0 != encoder->protected_);
300         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
301         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
302                 return false;
303         return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value);
304 }
305
306 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_qlp_coeff_precision(OggFLAC__StreamEncoder *encoder, unsigned value)
307 {
308         FLAC__ASSERT(0 != encoder);
309         FLAC__ASSERT(0 != encoder->private_);
310         FLAC__ASSERT(0 != encoder->protected_);
311         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
312         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
313                 return false;
314         return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value);
315 }
316
317 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
318 {
319         FLAC__ASSERT(0 != encoder);
320         FLAC__ASSERT(0 != encoder->private_);
321         FLAC__ASSERT(0 != encoder->protected_);
322         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
323         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
324                 return false;
325         return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value);
326 }
327
328 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_escape_coding(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
329 {
330         FLAC__ASSERT(0 != encoder);
331         FLAC__ASSERT(0 != encoder->private_);
332         FLAC__ASSERT(0 != encoder->protected_);
333         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
334         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
335                 return false;
336         return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value);
337 }
338
339 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_do_exhaustive_model_search(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
340 {
341         FLAC__ASSERT(0 != encoder);
342         FLAC__ASSERT(0 != encoder->private_);
343         FLAC__ASSERT(0 != encoder->protected_);
344         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
345         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
346                 return false;
347         return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value);
348 }
349
350 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_min_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value)
351 {
352         FLAC__ASSERT(0 != encoder);
353         FLAC__ASSERT(0 != encoder->private_);
354         FLAC__ASSERT(0 != encoder->protected_);
355         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
356         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
357                 return false;
358         return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
359 }
360
361 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_max_residual_partition_order(OggFLAC__StreamEncoder *encoder, unsigned value)
362 {
363         FLAC__ASSERT(0 != encoder);
364         FLAC__ASSERT(0 != encoder->private_);
365         FLAC__ASSERT(0 != encoder->protected_);
366         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
367         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
368                 return false;
369         return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
370 }
371
372 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_rice_parameter_search_dist(OggFLAC__StreamEncoder *encoder, unsigned value)
373 {
374         FLAC__ASSERT(0 != encoder);
375         FLAC__ASSERT(0 != encoder->private_);
376         FLAC__ASSERT(0 != encoder->protected_);
377         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
378         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
379                 return false;
380         return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value);
381 }
382
383 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_total_samples_estimate(OggFLAC__StreamEncoder *encoder, FLAC__uint64 value)
384 {
385         FLAC__ASSERT(0 != encoder);
386         FLAC__ASSERT(0 != encoder->private_);
387         FLAC__ASSERT(0 != encoder->protected_);
388         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
389         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
390                 return false;
391         return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value);
392 }
393
394 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_metadata(OggFLAC__StreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
395 {
396         FLAC__ASSERT(0 != encoder);
397         FLAC__ASSERT(0 != encoder->private_);
398         FLAC__ASSERT(0 != encoder->protected_);
399         FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
400         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
401                 return false;
402         return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
403 }
404
405 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_write_callback(OggFLAC__StreamEncoder *encoder, OggFLAC__StreamEncoderWriteCallback value)
406 {
407         FLAC__ASSERT(0 != encoder);
408         FLAC__ASSERT(0 != encoder->private_);
409         FLAC__ASSERT(0 != encoder->protected_);
410         FLAC__ASSERT(0 != value);
411         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
412                 return false;
413         encoder->private_->write_callback = value;
414         return true;
415 }
416
417 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_set_client_data(OggFLAC__StreamEncoder *encoder, void *value)
418 {
419         FLAC__ASSERT(0 != encoder);
420         FLAC__ASSERT(0 != encoder->private_);
421         FLAC__ASSERT(0 != encoder->protected_);
422         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
423                 return false;
424         encoder->private_->client_data = value;
425         return true;
426 }
427
428 /*
429  * These three functions are not static, but not publically exposed in
430  * include/FLAC/ either.  They are used by the test suite.
431  */
432 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_constant_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
433 {
434         FLAC__ASSERT(0 != encoder);
435         FLAC__ASSERT(0 != encoder->private_);
436         FLAC__ASSERT(0 != encoder->protected_);
437         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
438                 return false;
439         return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value);
440 }
441
442 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_fixed_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
443 {
444         FLAC__ASSERT(0 != encoder);
445         FLAC__ASSERT(0 != encoder->private_);
446         FLAC__ASSERT(0 != encoder->protected_);
447         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
448                 return false;
449         return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value);
450 }
451
452 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_disable_verbatim_subframes(OggFLAC__StreamEncoder *encoder, FLAC__bool value)
453 {
454         FLAC__ASSERT(0 != encoder);
455         FLAC__ASSERT(0 != encoder->private_);
456         FLAC__ASSERT(0 != encoder->protected_);
457         if(encoder->protected_->state != OggFLAC__STREAM_ENCODER_UNINITIALIZED)
458                 return false;
459         return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value);
460 }
461
462 OggFLAC_API OggFLAC__StreamEncoderState OggFLAC__stream_encoder_get_state(const OggFLAC__StreamEncoder *encoder)
463 {
464         FLAC__ASSERT(0 != encoder);
465         FLAC__ASSERT(0 != encoder->private_);
466         FLAC__ASSERT(0 != encoder->protected_);
467         return encoder->protected_->state;
468 }
469
470 OggFLAC_API FLAC__StreamEncoderState OggFLAC__stream_encoder_get_FLAC_stream_encoder_state(const OggFLAC__StreamEncoder *encoder)
471 {
472         FLAC__ASSERT(0 != encoder);
473         FLAC__ASSERT(0 != encoder->private_);
474         FLAC__ASSERT(0 != encoder->protected_);
475         return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder);
476 }
477
478 OggFLAC_API FLAC__StreamDecoderState OggFLAC__stream_encoder_get_verify_decoder_state(const OggFLAC__StreamEncoder *encoder)
479 {
480         FLAC__ASSERT(0 != encoder);
481         FLAC__ASSERT(0 != encoder->private_);
482         FLAC__ASSERT(0 != encoder->protected_);
483         return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder);
484 }
485
486 OggFLAC_API void OggFLAC__stream_encoder_get_verify_decoder_error_stats(const OggFLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
487 {
488         FLAC__ASSERT(0 != encoder);
489         FLAC__ASSERT(0 != encoder->private_);
490         FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
491 }
492
493 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_verify(const OggFLAC__StreamEncoder *encoder)
494 {
495         FLAC__ASSERT(0 != encoder);
496         FLAC__ASSERT(0 != encoder->private_);
497         FLAC__ASSERT(0 != encoder->protected_);
498         return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder);
499 }
500
501 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_streamable_subset(const OggFLAC__StreamEncoder *encoder)
502 {
503         FLAC__ASSERT(0 != encoder);
504         FLAC__ASSERT(0 != encoder->private_);
505         FLAC__ASSERT(0 != encoder->protected_);
506         return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder);
507 }
508
509 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_mid_side_stereo(const OggFLAC__StreamEncoder *encoder)
510 {
511         FLAC__ASSERT(0 != encoder);
512         FLAC__ASSERT(0 != encoder->private_);
513         FLAC__ASSERT(0 != encoder->protected_);
514         return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
515 }
516
517 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_loose_mid_side_stereo(const OggFLAC__StreamEncoder *encoder)
518 {
519         FLAC__ASSERT(0 != encoder);
520         FLAC__ASSERT(0 != encoder->private_);
521         FLAC__ASSERT(0 != encoder->protected_);
522         return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
523 }
524
525 OggFLAC_API unsigned OggFLAC__stream_encoder_get_channels(const OggFLAC__StreamEncoder *encoder)
526 {
527         FLAC__ASSERT(0 != encoder);
528         FLAC__ASSERT(0 != encoder->private_);
529         FLAC__ASSERT(0 != encoder->protected_);
530         return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder);
531 }
532
533 OggFLAC_API unsigned OggFLAC__stream_encoder_get_bits_per_sample(const OggFLAC__StreamEncoder *encoder)
534 {
535         FLAC__ASSERT(0 != encoder);
536         FLAC__ASSERT(0 != encoder->private_);
537         FLAC__ASSERT(0 != encoder->protected_);
538         return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder);
539 }
540
541 OggFLAC_API unsigned OggFLAC__stream_encoder_get_sample_rate(const OggFLAC__StreamEncoder *encoder)
542 {
543         FLAC__ASSERT(0 != encoder);
544         FLAC__ASSERT(0 != encoder->private_);
545         FLAC__ASSERT(0 != encoder->protected_);
546         return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder);
547 }
548
549 OggFLAC_API unsigned OggFLAC__stream_encoder_get_blocksize(const OggFLAC__StreamEncoder *encoder)
550 {
551         FLAC__ASSERT(0 != encoder);
552         FLAC__ASSERT(0 != encoder->private_);
553         FLAC__ASSERT(0 != encoder->protected_);
554         return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
555 }
556
557 OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_lpc_order(const OggFLAC__StreamEncoder *encoder)
558 {
559         FLAC__ASSERT(0 != encoder);
560         FLAC__ASSERT(0 != encoder->private_);
561         FLAC__ASSERT(0 != encoder->protected_);
562         return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder);
563 }
564
565 OggFLAC_API unsigned OggFLAC__stream_encoder_get_qlp_coeff_precision(const OggFLAC__StreamEncoder *encoder)
566 {
567         FLAC__ASSERT(0 != encoder);
568         FLAC__ASSERT(0 != encoder->private_);
569         FLAC__ASSERT(0 != encoder->protected_);
570         return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder);
571 }
572
573 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__StreamEncoder *encoder)
574 {
575         FLAC__ASSERT(0 != encoder);
576         FLAC__ASSERT(0 != encoder->private_);
577         FLAC__ASSERT(0 != encoder->protected_);
578         return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder);
579 }
580
581 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_escape_coding(const OggFLAC__StreamEncoder *encoder)
582 {
583         FLAC__ASSERT(0 != encoder);
584         FLAC__ASSERT(0 != encoder->private_);
585         FLAC__ASSERT(0 != encoder->protected_);
586         return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder);
587 }
588
589 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_get_do_exhaustive_model_search(const OggFLAC__StreamEncoder *encoder)
590 {
591         FLAC__ASSERT(0 != encoder);
592         FLAC__ASSERT(0 != encoder->private_);
593         FLAC__ASSERT(0 != encoder->protected_);
594         return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder);
595 }
596
597 OggFLAC_API unsigned OggFLAC__stream_encoder_get_min_residual_partition_order(const OggFLAC__StreamEncoder *encoder)
598 {
599         FLAC__ASSERT(0 != encoder);
600         FLAC__ASSERT(0 != encoder->private_);
601         FLAC__ASSERT(0 != encoder->protected_);
602         return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder);
603 }
604
605 OggFLAC_API unsigned OggFLAC__stream_encoder_get_max_residual_partition_order(const OggFLAC__StreamEncoder *encoder)
606 {
607         FLAC__ASSERT(0 != encoder);
608         FLAC__ASSERT(0 != encoder->private_);
609         FLAC__ASSERT(0 != encoder->protected_);
610         return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder);
611 }
612
613 OggFLAC_API unsigned OggFLAC__stream_encoder_get_rice_parameter_search_dist(const OggFLAC__StreamEncoder *encoder)
614 {
615         FLAC__ASSERT(0 != encoder);
616         FLAC__ASSERT(0 != encoder->private_);
617         FLAC__ASSERT(0 != encoder->protected_);
618         return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder);
619 }
620
621 OggFLAC_API FLAC__uint64 OggFLAC__stream_encoder_get_total_samples_estimate(const OggFLAC__StreamEncoder *encoder)
622 {
623         FLAC__ASSERT(0 != encoder);
624         FLAC__ASSERT(0 != encoder->private_);
625         FLAC__ASSERT(0 != encoder->protected_);
626         return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
627 }
628
629 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process(OggFLAC__StreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
630 {
631         FLAC__ASSERT(0 != encoder);
632         FLAC__ASSERT(0 != encoder->private_);
633         FLAC__ASSERT(0 != encoder->protected_);
634         return FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples);
635 }
636
637 OggFLAC_API FLAC__bool OggFLAC__stream_encoder_process_interleaved(OggFLAC__StreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
638 {
639         FLAC__ASSERT(0 != encoder);
640         FLAC__ASSERT(0 != encoder->private_);
641         FLAC__ASSERT(0 != encoder->protected_);
642         return FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples);
643 }
644
645 /***********************************************************************
646  *
647  * Private class methods
648  *
649  ***********************************************************************/
650
651 void set_defaults_(OggFLAC__StreamEncoder *encoder)
652 {
653         FLAC__ASSERT(0 != encoder);
654
655         encoder->private_->write_callback = 0;
656         encoder->private_->client_data = 0;
657         encoder->protected_->serial_number = 0;
658 }
659
660 FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
661 {
662         OggFLAC__StreamEncoder *encoder = (OggFLAC__StreamEncoder*)client_data;
663         ogg_packet packet;
664         const FLAC__uint64 total_samples_estimate = FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
665         FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
666
667         encoder->private_->samples_written += samples;
668
669         memset(&packet, 0, sizeof(packet));
670         packet.packet = (unsigned char *)buffer;
671         packet.granulepos = encoder->private_->samples_written;
672         /* WATCHOUT:
673          * This depends on the behavior of FLAC__StreamEncoder that 'samples'
674          * will be 0 for metadata writes.
675          */
676         packet.packetno = (samples == 0? -1 : (int)current_frame);
677         packet.bytes = bytes;
678
679         if(encoder->private_->is_first_packet) {
680                 packet.b_o_s = 1;
681                 encoder->private_->is_first_packet = false;
682         }
683
684         if(total_samples_estimate > 0 && total_samples_estimate == encoder->private_->samples_written)
685                 packet.e_o_s = 1;
686
687         if(ogg_stream_packetin(&encoder->private_->ogg.stream_state, &packet) != 0)
688                 return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
689
690         while(ogg_stream_pageout(&encoder->private_->ogg.stream_state, &encoder->private_->ogg.page) != 0) {
691                 if(encoder->private_->write_callback(encoder, encoder->private_->ogg.page.header, encoder->private_->ogg.page.header_len, 0, current_frame, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
692                         return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
693
694                 if(encoder->private_->write_callback(encoder, encoder->private_->ogg.page.body, encoder->private_->ogg.page.body_len, 0, current_frame, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK)
695                         return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
696         }
697
698         return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
699 }
700
701 void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data)
702 {
703         /*
704          * We don't try to go back an update metadata blocks by mucking
705          * around inside the Ogg layer.  Maybe someday we will care to
706          * and an OggFLAC__SeekableStreamEncoder and OggFLAC__FileEncoder
707          * will be possible but it may just never be useful.
708          */
709         (void)encoder, (void)metadata, (void)client_data;
710 }