1 /* libOggFLAC - Free Lossless Audio Codec + Ogg library
2 * Copyright (C) 2002,2003,2004 Josh Coalson
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * - Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * - Neither the name of the Xiph.org Foundation nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include <stdlib.h> /* for calloc() */
34 #include <string.h> /* for memcpy() */
35 #include "FLAC/assert.h"
36 #include "OggFLAC/seekable_stream_encoder.h"
37 #include "protected/seekable_stream_encoder.h"
38 #include "private/ogg_helper.h"
43 #define max(a,b) ((a)>(b)?(a):(b))
45 /***********************************************************************
47 * Private class method prototypes
49 ***********************************************************************/
51 /* unpublished debug routines */
52 extern FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
53 extern FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
54 extern FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
56 static void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder);
57 static FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
58 static void metadata_callback_(const FLAC__StreamEncoder *encoder, const FLAC__StreamMetadata *metadata, void *client_data);
61 /***********************************************************************
65 ***********************************************************************/
67 typedef struct OggFLAC__SeekableStreamEncoderPrivate {
68 OggFLAC__SeekableStreamEncoderReadCallback read_callback;
69 OggFLAC__SeekableStreamEncoderSeekCallback seek_callback;
70 OggFLAC__SeekableStreamEncoderTellCallback tell_callback;
71 OggFLAC__SeekableStreamEncoderWriteCallback write_callback;
73 FLAC__StreamEncoder *FLAC_stream_encoder;
74 FLAC__StreamMetadata_SeekTable *seek_table;
75 /* internal vars (all the above are class settings) */
76 unsigned first_seekpoint_to_check;
77 FLAC__uint64 samples_written;
78 } OggFLAC__SeekableStreamEncoderPrivate;
81 /***********************************************************************
83 * Public static class data
85 ***********************************************************************/
87 OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderStateString[] = {
88 "OggFLAC__SEEKABLE_STREAM_ENCODER_OK",
89 "OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR",
90 "OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR",
91 "OggFLAC__SEEKABLE_STREAM_ENCODER_MEMORY_ALLOCATION_ERROR",
92 "OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR",
93 "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
94 "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_ERROR",
95 "OggFLAC__SEEKABLE_STREAM_ENCODER_SEEK_ERROR",
96 "OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR",
97 "OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED",
98 "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK",
99 "OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE",
100 "OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED"
103 OggFLAC_API const char * const OggFLAC__SeekableStreamEncoderReadStatusString[] = {
104 "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_CONTINUE",
105 "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_END_OF_STREAM",
106 "OggFLAC__SEEKABLE_STREAM_ENCODER_READ_STATUS_ABORT"
110 /***********************************************************************
112 * Class constructor/destructor
115 OggFLAC_API OggFLAC__SeekableStreamEncoder *OggFLAC__seekable_stream_encoder_new()
117 OggFLAC__SeekableStreamEncoder *encoder;
119 encoder = (OggFLAC__SeekableStreamEncoder*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoder));
124 encoder->protected_ = (OggFLAC__SeekableStreamEncoderProtected*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoderProtected));
125 if(encoder->protected_ == 0) {
130 encoder->private_ = (OggFLAC__SeekableStreamEncoderPrivate*)calloc(1, sizeof(OggFLAC__SeekableStreamEncoderPrivate));
131 if(encoder->private_ == 0) {
132 free(encoder->protected_);
137 encoder->private_->FLAC_stream_encoder = FLAC__stream_encoder_new();
138 if(0 == encoder->private_->FLAC_stream_encoder) {
139 free(encoder->private_);
140 free(encoder->protected_);
145 set_defaults_(encoder);
147 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
152 OggFLAC_API void OggFLAC__seekable_stream_encoder_delete(OggFLAC__SeekableStreamEncoder *encoder)
154 FLAC__ASSERT(0 != encoder);
155 FLAC__ASSERT(0 != encoder->protected_);
156 FLAC__ASSERT(0 != encoder->private_);
157 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
159 (void)OggFLAC__seekable_stream_encoder_finish(encoder);
161 FLAC__stream_encoder_delete(encoder->private_->FLAC_stream_encoder);
163 free(encoder->private_);
164 free(encoder->protected_);
169 /***********************************************************************
171 * Public class methods
173 ***********************************************************************/
175 OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_init(OggFLAC__SeekableStreamEncoder *encoder)
177 FLAC__ASSERT(0 != encoder);
179 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
180 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_ALREADY_INITIALIZED;
182 if(0 == encoder->private_->seek_callback || 0 == encoder->private_->tell_callback || 0 == encoder->private_->write_callback)
183 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_CALLBACK;
185 if(!OggFLAC__ogg_encoder_aspect_init(&encoder->protected_->ogg_encoder_aspect))
186 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
188 if(0 != encoder->private_->seek_table && !FLAC__format_seektable_is_legal(encoder->private_->seek_table))
189 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_INVALID_SEEKTABLE;
192 * These must be done before we init the stream encoder because that
193 * calls the write_callback, which uses these values.
195 encoder->private_->first_seekpoint_to_check = 0;
196 encoder->private_->samples_written = 0;
197 encoder->protected_->streaminfo_offset = 0;
198 encoder->protected_->seektable_offset = 0;
199 encoder->protected_->audio_offset = 0;
201 FLAC__stream_encoder_set_write_callback(encoder->private_->FLAC_stream_encoder, write_callback_);
202 FLAC__stream_encoder_set_metadata_callback(encoder->private_->FLAC_stream_encoder, metadata_callback_);
203 FLAC__stream_encoder_set_client_data(encoder->private_->FLAC_stream_encoder, encoder);
205 if(FLAC__stream_encoder_init(encoder->private_->FLAC_stream_encoder) != FLAC__STREAM_ENCODER_OK)
206 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
209 * Initializing the stream encoder writes all the metadata, so we
210 * save the stream offset now.
212 if(encoder->private_->tell_callback(encoder, &encoder->protected_->audio_offset, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK)
213 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR;
215 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OK;
218 OggFLAC_API void OggFLAC__seekable_stream_encoder_finish(OggFLAC__SeekableStreamEncoder *encoder)
220 FLAC__ASSERT(0 != encoder);
221 FLAC__ASSERT(0 != encoder->private_);
222 FLAC__ASSERT(0 != encoder->protected_);
224 if(encoder->protected_->state == OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
227 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
229 FLAC__stream_encoder_finish(encoder->private_->FLAC_stream_encoder);
231 OggFLAC__ogg_encoder_aspect_finish(&encoder->protected_->ogg_encoder_aspect);
233 set_defaults_(encoder);
235 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED;
238 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_serial_number(OggFLAC__SeekableStreamEncoder *encoder, long value)
240 FLAC__ASSERT(0 != encoder);
241 FLAC__ASSERT(0 != encoder->private_);
242 FLAC__ASSERT(0 != encoder->protected_);
243 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
244 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
246 OggFLAC__ogg_encoder_aspect_set_serial_number(&encoder->protected_->ogg_encoder_aspect, value);
250 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_verify(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
252 FLAC__ASSERT(0 != encoder);
253 FLAC__ASSERT(0 != encoder->private_);
254 FLAC__ASSERT(0 != encoder->protected_);
255 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
256 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
258 return FLAC__stream_encoder_set_verify(encoder->private_->FLAC_stream_encoder, value);
261 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_streamable_subset(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
263 FLAC__ASSERT(0 != encoder);
264 FLAC__ASSERT(0 != encoder->private_);
265 FLAC__ASSERT(0 != encoder->protected_);
266 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
267 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
269 return FLAC__stream_encoder_set_streamable_subset(encoder->private_->FLAC_stream_encoder, value);
272 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
274 FLAC__ASSERT(0 != encoder);
275 FLAC__ASSERT(0 != encoder->private_);
276 FLAC__ASSERT(0 != encoder->protected_);
277 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
278 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
280 return FLAC__stream_encoder_set_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
283 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_loose_mid_side_stereo(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
285 FLAC__ASSERT(0 != encoder);
286 FLAC__ASSERT(0 != encoder->private_);
287 FLAC__ASSERT(0 != encoder->protected_);
288 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
289 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
291 return FLAC__stream_encoder_set_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder, value);
294 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_channels(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
296 FLAC__ASSERT(0 != encoder);
297 FLAC__ASSERT(0 != encoder->private_);
298 FLAC__ASSERT(0 != encoder->protected_);
299 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
300 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
302 return FLAC__stream_encoder_set_channels(encoder->private_->FLAC_stream_encoder, value);
305 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_bits_per_sample(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
307 FLAC__ASSERT(0 != encoder);
308 FLAC__ASSERT(0 != encoder->private_);
309 FLAC__ASSERT(0 != encoder->protected_);
310 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
311 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
313 return FLAC__stream_encoder_set_bits_per_sample(encoder->private_->FLAC_stream_encoder, value);
316 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_sample_rate(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
318 FLAC__ASSERT(0 != encoder);
319 FLAC__ASSERT(0 != encoder->private_);
320 FLAC__ASSERT(0 != encoder->protected_);
321 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
322 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
324 return FLAC__stream_encoder_set_sample_rate(encoder->private_->FLAC_stream_encoder, value);
327 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_blocksize(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
329 FLAC__ASSERT(0 != encoder);
330 FLAC__ASSERT(0 != encoder->private_);
331 FLAC__ASSERT(0 != encoder->protected_);
332 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
333 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
335 return FLAC__stream_encoder_set_blocksize(encoder->private_->FLAC_stream_encoder, value);
338 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_lpc_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
340 FLAC__ASSERT(0 != encoder);
341 FLAC__ASSERT(0 != encoder->private_);
342 FLAC__ASSERT(0 != encoder->protected_);
343 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
344 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
346 return FLAC__stream_encoder_set_max_lpc_order(encoder->private_->FLAC_stream_encoder, value);
349 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_qlp_coeff_precision(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
351 FLAC__ASSERT(0 != encoder);
352 FLAC__ASSERT(0 != encoder->private_);
353 FLAC__ASSERT(0 != encoder->protected_);
354 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
355 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
357 return FLAC__stream_encoder_set_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder, value);
360 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_qlp_coeff_prec_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
362 FLAC__ASSERT(0 != encoder);
363 FLAC__ASSERT(0 != encoder->private_);
364 FLAC__ASSERT(0 != encoder->protected_);
365 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
366 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
368 return FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder, value);
371 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_escape_coding(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
373 FLAC__ASSERT(0 != encoder);
374 FLAC__ASSERT(0 != encoder->private_);
375 FLAC__ASSERT(0 != encoder->protected_);
376 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
377 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
379 return FLAC__stream_encoder_set_do_escape_coding(encoder->private_->FLAC_stream_encoder, value);
382 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_do_exhaustive_model_search(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
384 FLAC__ASSERT(0 != encoder);
385 FLAC__ASSERT(0 != encoder->private_);
386 FLAC__ASSERT(0 != encoder->protected_);
387 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
388 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
390 return FLAC__stream_encoder_set_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder, value);
393 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_min_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
395 FLAC__ASSERT(0 != encoder);
396 FLAC__ASSERT(0 != encoder->private_);
397 FLAC__ASSERT(0 != encoder->protected_);
398 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
399 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
401 return FLAC__stream_encoder_set_min_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
404 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_max_residual_partition_order(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
406 FLAC__ASSERT(0 != encoder);
407 FLAC__ASSERT(0 != encoder->private_);
408 FLAC__ASSERT(0 != encoder->protected_);
409 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
410 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
412 return FLAC__stream_encoder_set_max_residual_partition_order(encoder->private_->FLAC_stream_encoder, value);
415 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_rice_parameter_search_dist(OggFLAC__SeekableStreamEncoder *encoder, unsigned value)
417 FLAC__ASSERT(0 != encoder);
418 FLAC__ASSERT(0 != encoder->private_);
419 FLAC__ASSERT(0 != encoder->protected_);
420 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
421 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
423 return FLAC__stream_encoder_set_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder, value);
426 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_total_samples_estimate(OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 value)
428 FLAC__ASSERT(0 != encoder);
429 FLAC__ASSERT(0 != encoder->private_);
430 FLAC__ASSERT(0 != encoder->protected_);
431 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
432 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
434 return FLAC__stream_encoder_set_total_samples_estimate(encoder->private_->FLAC_stream_encoder, value);
437 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_metadata(OggFLAC__SeekableStreamEncoder *encoder, FLAC__StreamMetadata **metadata, unsigned num_blocks)
439 FLAC__ASSERT(0 != encoder);
440 FLAC__ASSERT(0 != encoder->private_);
441 FLAC__ASSERT(0 != encoder->protected_);
442 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
443 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
445 if(0 != metadata && num_blocks > 0) {
447 for(i = 0; i < num_blocks; i++) {
448 if(0 != metadata[i] && metadata[i]->type == FLAC__METADATA_TYPE_SEEKTABLE) {
449 encoder->private_->seek_table = &metadata[i]->data.seek_table;
450 break; /* take only the first one */
454 return FLAC__stream_encoder_set_metadata(encoder->private_->FLAC_stream_encoder, metadata, num_blocks);
457 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_read_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderReadCallback value)
459 FLAC__ASSERT(0 != encoder);
460 FLAC__ASSERT(0 != encoder->private_);
461 FLAC__ASSERT(0 != encoder->protected_);
462 FLAC__ASSERT(0 != value);
463 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
465 encoder->private_->read_callback = value;
469 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_seek_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderSeekCallback value)
471 FLAC__ASSERT(0 != encoder);
472 FLAC__ASSERT(0 != encoder->private_);
473 FLAC__ASSERT(0 != encoder->protected_);
474 FLAC__ASSERT(0 != value);
475 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
477 encoder->private_->seek_callback = value;
481 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_tell_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderTellCallback value)
483 FLAC__ASSERT(0 != encoder);
484 FLAC__ASSERT(0 != encoder->private_);
485 FLAC__ASSERT(0 != encoder->protected_);
486 FLAC__ASSERT(0 != value);
487 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
489 encoder->private_->tell_callback = value;
493 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_write_callback(OggFLAC__SeekableStreamEncoder *encoder, OggFLAC__SeekableStreamEncoderWriteCallback value)
495 FLAC__ASSERT(0 != encoder);
496 FLAC__ASSERT(0 != encoder->private_);
497 FLAC__ASSERT(0 != encoder->protected_);
498 FLAC__ASSERT(0 != value);
499 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
501 encoder->private_->write_callback = value;
505 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_set_client_data(OggFLAC__SeekableStreamEncoder *encoder, void *value)
507 FLAC__ASSERT(0 != encoder);
508 FLAC__ASSERT(0 != encoder->private_);
509 FLAC__ASSERT(0 != encoder->protected_);
510 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
512 encoder->private_->client_data = value;
517 * These three functions are not static, but not publically exposed in
518 * include/FLAC/ either. They are used by the test suite.
520 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_constant_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
522 FLAC__ASSERT(0 != encoder);
523 FLAC__ASSERT(0 != encoder->private_);
524 FLAC__ASSERT(0 != encoder->protected_);
525 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
527 return FLAC__stream_encoder_disable_constant_subframes(encoder->private_->FLAC_stream_encoder, value);
530 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_fixed_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
532 FLAC__ASSERT(0 != encoder);
533 FLAC__ASSERT(0 != encoder->private_);
534 FLAC__ASSERT(0 != encoder->protected_);
535 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
537 return FLAC__stream_encoder_disable_fixed_subframes(encoder->private_->FLAC_stream_encoder, value);
540 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_disable_verbatim_subframes(OggFLAC__SeekableStreamEncoder *encoder, FLAC__bool value)
542 FLAC__ASSERT(0 != encoder);
543 FLAC__ASSERT(0 != encoder->private_);
544 FLAC__ASSERT(0 != encoder->protected_);
545 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_UNINITIALIZED)
547 return FLAC__stream_encoder_disable_verbatim_subframes(encoder->private_->FLAC_stream_encoder, value);
550 OggFLAC_API OggFLAC__SeekableStreamEncoderState OggFLAC__seekable_stream_encoder_get_state(const OggFLAC__SeekableStreamEncoder *encoder)
552 FLAC__ASSERT(0 != encoder);
553 FLAC__ASSERT(0 != encoder->private_);
554 FLAC__ASSERT(0 != encoder->protected_);
555 return encoder->protected_->state;
558 OggFLAC_API FLAC__StreamEncoderState OggFLAC__seekable_stream_encoder_get_FLAC_stream_encoder_state(const OggFLAC__SeekableStreamEncoder *encoder)
560 FLAC__ASSERT(0 != encoder);
561 FLAC__ASSERT(0 != encoder->private_);
562 FLAC__ASSERT(0 != encoder->protected_);
563 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
564 return FLAC__stream_encoder_get_state(encoder->private_->FLAC_stream_encoder);
567 OggFLAC_API FLAC__StreamDecoderState OggFLAC__seekable_stream_encoder_get_verify_decoder_state(const OggFLAC__SeekableStreamEncoder *encoder)
569 FLAC__ASSERT(0 != encoder);
570 FLAC__ASSERT(0 != encoder->private_);
571 FLAC__ASSERT(0 != encoder->protected_);
572 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
573 return FLAC__stream_encoder_get_verify_decoder_state(encoder->private_->FLAC_stream_encoder);
576 OggFLAC_API const char *OggFLAC__seekable_stream_encoder_get_resolved_state_string(const OggFLAC__SeekableStreamEncoder *encoder)
578 FLAC__ASSERT(0 != encoder);
579 FLAC__ASSERT(0 != encoder->private_);
580 FLAC__ASSERT(0 != encoder->protected_);
581 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
582 if(encoder->protected_->state != OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR)
583 return OggFLAC__SeekableStreamEncoderStateString[encoder->protected_->state];
585 return FLAC__stream_encoder_get_resolved_state_string(encoder->private_->FLAC_stream_encoder);
588 OggFLAC_API void OggFLAC__seekable_stream_encoder_get_verify_decoder_error_stats(const OggFLAC__SeekableStreamEncoder *encoder, FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
590 FLAC__ASSERT(0 != encoder);
591 FLAC__ASSERT(0 != encoder->private_);
592 FLAC__ASSERT(0 != encoder->protected_);
593 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
594 FLAC__stream_encoder_get_verify_decoder_error_stats(encoder->private_->FLAC_stream_encoder, absolute_sample, frame_number, channel, sample, expected, got);
597 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_verify(const OggFLAC__SeekableStreamEncoder *encoder)
599 FLAC__ASSERT(0 != encoder);
600 FLAC__ASSERT(0 != encoder->private_);
601 FLAC__ASSERT(0 != encoder->protected_);
602 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
603 return FLAC__stream_encoder_get_verify(encoder->private_->FLAC_stream_encoder);
606 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_streamable_subset(const OggFLAC__SeekableStreamEncoder *encoder)
608 FLAC__ASSERT(0 != encoder);
609 FLAC__ASSERT(0 != encoder->private_);
610 FLAC__ASSERT(0 != encoder->protected_);
611 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
612 return FLAC__stream_encoder_get_streamable_subset(encoder->private_->FLAC_stream_encoder);
615 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder)
617 FLAC__ASSERT(0 != encoder);
618 FLAC__ASSERT(0 != encoder->private_);
619 FLAC__ASSERT(0 != encoder->protected_);
620 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
621 return FLAC__stream_encoder_get_do_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
624 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_loose_mid_side_stereo(const OggFLAC__SeekableStreamEncoder *encoder)
626 FLAC__ASSERT(0 != encoder);
627 FLAC__ASSERT(0 != encoder->private_);
628 FLAC__ASSERT(0 != encoder->protected_);
629 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
630 return FLAC__stream_encoder_get_loose_mid_side_stereo(encoder->private_->FLAC_stream_encoder);
633 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_channels(const OggFLAC__SeekableStreamEncoder *encoder)
635 FLAC__ASSERT(0 != encoder);
636 FLAC__ASSERT(0 != encoder->private_);
637 FLAC__ASSERT(0 != encoder->protected_);
638 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
639 return FLAC__stream_encoder_get_channels(encoder->private_->FLAC_stream_encoder);
642 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_bits_per_sample(const OggFLAC__SeekableStreamEncoder *encoder)
644 FLAC__ASSERT(0 != encoder);
645 FLAC__ASSERT(0 != encoder->private_);
646 FLAC__ASSERT(0 != encoder->protected_);
647 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
648 return FLAC__stream_encoder_get_bits_per_sample(encoder->private_->FLAC_stream_encoder);
651 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_sample_rate(const OggFLAC__SeekableStreamEncoder *encoder)
653 FLAC__ASSERT(0 != encoder);
654 FLAC__ASSERT(0 != encoder->private_);
655 FLAC__ASSERT(0 != encoder->protected_);
656 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
657 return FLAC__stream_encoder_get_sample_rate(encoder->private_->FLAC_stream_encoder);
660 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_blocksize(const OggFLAC__SeekableStreamEncoder *encoder)
662 FLAC__ASSERT(0 != encoder);
663 FLAC__ASSERT(0 != encoder->private_);
664 FLAC__ASSERT(0 != encoder->protected_);
665 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
666 return FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
669 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_lpc_order(const OggFLAC__SeekableStreamEncoder *encoder)
671 FLAC__ASSERT(0 != encoder);
672 FLAC__ASSERT(0 != encoder->private_);
673 FLAC__ASSERT(0 != encoder->protected_);
674 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
675 return FLAC__stream_encoder_get_max_lpc_order(encoder->private_->FLAC_stream_encoder);
678 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_qlp_coeff_precision(const OggFLAC__SeekableStreamEncoder *encoder)
680 FLAC__ASSERT(0 != encoder);
681 FLAC__ASSERT(0 != encoder->private_);
682 FLAC__ASSERT(0 != encoder->protected_);
683 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
684 return FLAC__stream_encoder_get_qlp_coeff_precision(encoder->private_->FLAC_stream_encoder);
687 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_qlp_coeff_prec_search(const OggFLAC__SeekableStreamEncoder *encoder)
689 FLAC__ASSERT(0 != encoder);
690 FLAC__ASSERT(0 != encoder->private_);
691 FLAC__ASSERT(0 != encoder->protected_);
692 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
693 return FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder->private_->FLAC_stream_encoder);
696 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_escape_coding(const OggFLAC__SeekableStreamEncoder *encoder)
698 FLAC__ASSERT(0 != encoder);
699 FLAC__ASSERT(0 != encoder->private_);
700 FLAC__ASSERT(0 != encoder->protected_);
701 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
702 return FLAC__stream_encoder_get_do_escape_coding(encoder->private_->FLAC_stream_encoder);
705 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_get_do_exhaustive_model_search(const OggFLAC__SeekableStreamEncoder *encoder)
707 FLAC__ASSERT(0 != encoder);
708 FLAC__ASSERT(0 != encoder->private_);
709 FLAC__ASSERT(0 != encoder->protected_);
710 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
711 return FLAC__stream_encoder_get_do_exhaustive_model_search(encoder->private_->FLAC_stream_encoder);
714 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_min_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder)
716 FLAC__ASSERT(0 != encoder);
717 FLAC__ASSERT(0 != encoder->private_);
718 FLAC__ASSERT(0 != encoder->protected_);
719 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
720 return FLAC__stream_encoder_get_min_residual_partition_order(encoder->private_->FLAC_stream_encoder);
723 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_max_residual_partition_order(const OggFLAC__SeekableStreamEncoder *encoder)
725 FLAC__ASSERT(0 != encoder);
726 FLAC__ASSERT(0 != encoder->private_);
727 FLAC__ASSERT(0 != encoder->protected_);
728 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
729 return FLAC__stream_encoder_get_max_residual_partition_order(encoder->private_->FLAC_stream_encoder);
732 OggFLAC_API unsigned OggFLAC__seekable_stream_encoder_get_rice_parameter_search_dist(const OggFLAC__SeekableStreamEncoder *encoder)
734 FLAC__ASSERT(0 != encoder);
735 FLAC__ASSERT(0 != encoder->private_);
736 FLAC__ASSERT(0 != encoder->protected_);
737 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
738 return FLAC__stream_encoder_get_rice_parameter_search_dist(encoder->private_->FLAC_stream_encoder);
741 OggFLAC_API FLAC__uint64 OggFLAC__seekable_stream_encoder_get_total_samples_estimate(const OggFLAC__SeekableStreamEncoder *encoder)
743 FLAC__ASSERT(0 != encoder);
744 FLAC__ASSERT(0 != encoder->private_);
745 FLAC__ASSERT(0 != encoder->protected_);
746 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
747 return FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder);
750 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 * const buffer[], unsigned samples)
752 FLAC__ASSERT(0 != encoder);
753 FLAC__ASSERT(0 != encoder->private_);
754 FLAC__ASSERT(0 != encoder->protected_);
755 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
756 if(!FLAC__stream_encoder_process(encoder->private_->FLAC_stream_encoder, buffer, samples)) {
757 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
764 OggFLAC_API FLAC__bool OggFLAC__seekable_stream_encoder_process_interleaved(OggFLAC__SeekableStreamEncoder *encoder, const FLAC__int32 buffer[], unsigned samples)
766 FLAC__ASSERT(0 != encoder);
767 FLAC__ASSERT(0 != encoder->private_);
768 FLAC__ASSERT(0 != encoder->protected_);
769 FLAC__ASSERT(0 != encoder->private_->FLAC_stream_encoder);
770 if(!FLAC__stream_encoder_process_interleaved(encoder->private_->FLAC_stream_encoder, buffer, samples)) {
771 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_FLAC_STREAM_ENCODER_ERROR;
778 /***********************************************************************
780 * Private class methods
782 ***********************************************************************/
784 void set_defaults_(OggFLAC__SeekableStreamEncoder *encoder)
786 FLAC__ASSERT(0 != encoder);
787 FLAC__ASSERT(0 != encoder->private_);
788 FLAC__ASSERT(0 != encoder->protected_);
790 encoder->private_->seek_callback = 0;
791 encoder->private_->tell_callback = 0;
792 encoder->private_->write_callback = 0;
793 encoder->private_->client_data = 0;
795 encoder->private_->seek_table = 0;
797 OggFLAC__ogg_encoder_aspect_set_defaults(&encoder->protected_->ogg_encoder_aspect);
800 FLAC__StreamEncoderWriteStatus write_callback_(const FLAC__StreamEncoder *unused, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
802 OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data;
803 FLAC__StreamEncoderWriteStatus status;
804 FLAC__uint64 output_position;
806 (void)unused; /* silence compiler warning about unused parameter */
807 FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
809 if(encoder->private_->tell_callback(encoder, &output_position, encoder->private_->client_data) != FLAC__SEEKABLE_STREAM_ENCODER_TELL_STATUS_OK)
810 return encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_TELL_ERROR;
813 * Watch for the STREAMINFO block and first SEEKTABLE block to go by and store their offsets.
816 FLAC__MetadataType type = (buffer[0] & 0x7f);
817 if(type == FLAC__METADATA_TYPE_STREAMINFO)
818 encoder->protected_->streaminfo_offset = output_position;
819 else if(type == FLAC__METADATA_TYPE_SEEKTABLE && encoder->protected_->seektable_offset == 0)
820 encoder->protected_->seektable_offset = output_position;
824 * Mark the current seek point if hit (if audio_offset == 0 that
825 * means we're still writing metadata and haven't hit the first
828 if(0 != encoder->private_->seek_table && encoder->protected_->audio_offset > 0 && encoder->private_->seek_table->num_points > 0) {
829 const unsigned blocksize = FLAC__stream_encoder_get_blocksize(encoder->private_->FLAC_stream_encoder);
830 const FLAC__uint64 frame_first_sample = encoder->private_->samples_written;
831 const FLAC__uint64 frame_last_sample = frame_first_sample + (FLAC__uint64)blocksize - 1;
832 FLAC__uint64 test_sample;
834 for(i = encoder->private_->first_seekpoint_to_check; i < encoder->private_->seek_table->num_points; i++) {
835 test_sample = encoder->private_->seek_table->points[i].sample_number;
836 if(test_sample > frame_last_sample) {
839 else if(test_sample >= frame_first_sample) {
840 encoder->private_->seek_table->points[i].sample_number = frame_first_sample;
841 encoder->private_->seek_table->points[i].stream_offset = output_position - encoder->protected_->audio_offset;
842 encoder->private_->seek_table->points[i].frame_samples = blocksize;
843 encoder->private_->first_seekpoint_to_check++;
844 /* DO NOT: "break;" and here's why:
845 * The seektable template may contain more than one target
846 * sample for any given frame; we will keep looping, generating
847 * duplicate seekpoints for them, and we'll clean it up later,
848 * just before writing the seektable back to the metadata.
852 encoder->private_->first_seekpoint_to_check++;
857 status = OggFLAC__ogg_encoder_aspect_write_callback_wrapper(&encoder->protected_->ogg_encoder_aspect, FLAC__stream_encoder_get_total_samples_estimate(encoder->private_->FLAC_stream_encoder), buffer, bytes, samples, current_frame, (OggFLAC__OggEncoderAspectWriteCallbackProxy)encoder->private_->write_callback, encoder, encoder->private_->client_data);
859 if(status == FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
860 encoder->private_->samples_written += samples;
863 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
868 void metadata_callback_(const FLAC__StreamEncoder *unused, const FLAC__StreamMetadata *metadata, void *client_data)
870 OggFLAC__SeekableStreamEncoder *encoder = (OggFLAC__SeekableStreamEncoder*)client_data;
871 FLAC__byte b[max(6, FLAC__STREAM_METADATA_SEEKPOINT_LENGTH)];
872 const FLAC__uint64 samples = metadata->data.stream_info.total_samples;
873 const unsigned min_framesize = metadata->data.stream_info.min_framesize;
874 const unsigned max_framesize = metadata->data.stream_info.max_framesize;
877 FLAC__ASSERT(metadata->type == FLAC__METADATA_TYPE_STREAMINFO);
879 /* We get called by the stream encoder when the encoding process
880 * has finished so that we can update the STREAMINFO and SEEKTABLE
884 (void)unused; /* silence compiler warning about unused parameter */
885 FLAC__ASSERT(encoder->private_->FLAC_stream_encoder == unused);
887 /*@@@ reopen callback here? The docs currently require user to open files in update mode from the start */
889 /* All this is based on intimate knowledge of the stream header
890 * layout, but a change to the header format that would break this
891 * would also break all streams encoded in the previous format.
895 * Write STREAMINFO stats
897 simple_ogg_page__init(&page);
898 if(!simple_ogg_page__get_at(encoder, encoder->protected_->streaminfo_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data))
899 return; /* state already set */
904 const unsigned md5_offset =
905 FLAC__STREAM_METADATA_HEADER_LENGTH +
907 FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
908 FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
909 FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
910 FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
911 FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
912 FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
913 FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN +
914 FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN
917 if(md5_offset + 16 > (unsigned)page.body_len) {
918 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
921 memcpy(page.body + md5_offset, metadata->data.stream_info.md5sum, 16);
927 const unsigned total_samples_byte_offset =
928 FLAC__STREAM_METADATA_HEADER_LENGTH +
930 FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
931 FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN +
932 FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN +
933 FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN +
934 FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN +
935 FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN +
936 FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN
940 if(total_samples_byte_offset + 5 > (unsigned)page.body_len) {
941 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
944 b[0] = (FLAC__byte)page.body[total_samples_byte_offset] & 0xF0;
945 b[0] |= (FLAC__byte)((samples >> 32) & 0x0F);
946 b[1] = (FLAC__byte)((samples >> 24) & 0xFF);
947 b[2] = (FLAC__byte)((samples >> 16) & 0xFF);
948 b[3] = (FLAC__byte)((samples >> 8) & 0xFF);
949 b[4] = (FLAC__byte)(samples & 0xFF);
950 memcpy(page.body + total_samples_byte_offset, b, 5);
956 const unsigned min_framesize_offset =
957 FLAC__STREAM_METADATA_HEADER_LENGTH +
959 FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN +
960 FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN
963 if(min_framesize_offset + 6 > (unsigned)page.body_len) {
964 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
967 b[0] = (FLAC__byte)((min_framesize >> 16) & 0xFF);
968 b[1] = (FLAC__byte)((min_framesize >> 8) & 0xFF);
969 b[2] = (FLAC__byte)(min_framesize & 0xFF);
970 b[3] = (FLAC__byte)((max_framesize >> 16) & 0xFF);
971 b[4] = (FLAC__byte)((max_framesize >> 8) & 0xFF);
972 b[5] = (FLAC__byte)(max_framesize & 0xFF);
973 memcpy(page.body + min_framesize_offset, b, 6);
979 if(0 != encoder->private_->seek_table && encoder->private_->seek_table->num_points > 0 && encoder->protected_->seektable_offset > 0) {
983 FLAC__format_seektable_sort(encoder->private_->seek_table);
985 FLAC__ASSERT(FLAC__format_seektable_is_legal(encoder->private_->seek_table));
987 simple_ogg_page__init(&page);
988 if(!simple_ogg_page__get_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->read_callback, encoder->private_->client_data))
989 return; /* state already set */
991 if(FLAC__STREAM_METADATA_HEADER_LENGTH + (18*encoder->private_->seek_table->num_points) > (unsigned)page.body_len) {
992 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_OGG_ERROR;
996 for(i = 0, p = page.body + FLAC__STREAM_METADATA_HEADER_LENGTH; i < encoder->private_->seek_table->num_points; i++, p += 18) {
999 xx = encoder->private_->seek_table->points[i].sample_number;
1000 b[7] = (FLAC__byte)xx; xx >>= 8;
1001 b[6] = (FLAC__byte)xx; xx >>= 8;
1002 b[5] = (FLAC__byte)xx; xx >>= 8;
1003 b[4] = (FLAC__byte)xx; xx >>= 8;
1004 b[3] = (FLAC__byte)xx; xx >>= 8;
1005 b[2] = (FLAC__byte)xx; xx >>= 8;
1006 b[1] = (FLAC__byte)xx; xx >>= 8;
1007 b[0] = (FLAC__byte)xx; xx >>= 8;
1008 xx = encoder->private_->seek_table->points[i].stream_offset;
1009 b[15] = (FLAC__byte)xx; xx >>= 8;
1010 b[14] = (FLAC__byte)xx; xx >>= 8;
1011 b[13] = (FLAC__byte)xx; xx >>= 8;
1012 b[12] = (FLAC__byte)xx; xx >>= 8;
1013 b[11] = (FLAC__byte)xx; xx >>= 8;
1014 b[10] = (FLAC__byte)xx; xx >>= 8;
1015 b[9] = (FLAC__byte)xx; xx >>= 8;
1016 b[8] = (FLAC__byte)xx; xx >>= 8;
1017 x = encoder->private_->seek_table->points[i].frame_samples;
1018 b[17] = (FLAC__byte)x; x >>= 8;
1019 b[16] = (FLAC__byte)x; x >>= 8;
1020 if(encoder->private_->write_callback(encoder, b, 18, 0, 0, encoder->private_->client_data) != FLAC__STREAM_ENCODER_WRITE_STATUS_OK) {
1021 encoder->protected_->state = OggFLAC__SEEKABLE_STREAM_ENCODER_WRITE_ERROR;
1027 if(!simple_ogg_page__set_at(encoder, encoder->protected_->seektable_offset, &page, encoder->private_->seek_callback, encoder->private_->write_callback, encoder->private_->client_data))
1028 return; /* state already set */
1029 simple_ogg_page__clear(&page);