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