merge libOggFLAC into libFLAC and libOggFLAC++ into FLAC++; documentation still needs...
[platform/upstream/flac.git] / src / libFLAC++ / stream_encoder.cpp
1 /* libFLAC++ - Free Lossless Audio Codec library
2  * Copyright (C) 2002,2003,2004,2005,2006  Josh Coalson
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * - Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  *
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.
14  *
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.
18  *
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.
30  */
31
32 #include "FLAC++/encoder.h"
33 #include "FLAC++/metadata.h"
34 #include "FLAC/assert.h"
35
36 #ifdef _MSC_VER
37 // warning C4800: 'int' : forcing to bool 'true' or 'false' (performance warning)
38 #pragma warning ( disable : 4800 )
39 #endif
40
41 namespace FLAC {
42         namespace Encoder {
43
44                 // ------------------------------------------------------------
45                 //
46                 // Stream
47                 //
48                 // ------------------------------------------------------------
49
50                 Stream::Stream():
51                 encoder_(::FLAC__stream_encoder_new())
52                 { }
53
54                 Stream::Stream(::FLAC__StreamEncoder *encoder):
55                 encoder_(encoder)
56                 { }
57
58                 Stream::~Stream()
59                 {
60                         // WATCHOUT: must check for NULL not only because
61                         // ::FLAC__stream_encoder_new() might have failed in
62                         // the constructor, but also because
63                         // OggFLAC::Encoder::Stream deletes the encoder_ before
64                         // we get to it here to make the C inheritance magic
65                         // work.
66                         if(0 != encoder_) {
67                                 ::FLAC__stream_encoder_finish(encoder_);
68                                 ::FLAC__stream_encoder_delete(encoder_);
69                         }
70                 }
71
72                 bool Stream::is_valid() const
73                 {
74                         return 0 != encoder_;
75                 }
76
77                 bool Stream::set_serial_number(long value)
78                 {
79                         FLAC__ASSERT(is_valid());
80                         return (bool)::FLAC__stream_encoder_set_serial_number(encoder_, value);
81                 }
82
83                 bool Stream::set_verify(bool value)
84                 {
85                         FLAC__ASSERT(is_valid());
86                         return (bool)::FLAC__stream_encoder_set_verify(encoder_, value);
87                 }
88
89                 bool Stream::set_streamable_subset(bool value)
90                 {
91                         FLAC__ASSERT(is_valid());
92                         return (bool)::FLAC__stream_encoder_set_streamable_subset(encoder_, value);
93                 }
94
95                 bool Stream::set_do_mid_side_stereo(bool value)
96                 {
97                         FLAC__ASSERT(is_valid());
98                         return (bool)::FLAC__stream_encoder_set_do_mid_side_stereo(encoder_, value);
99                 }
100
101                 bool Stream::set_loose_mid_side_stereo(bool value)
102                 {
103                         FLAC__ASSERT(is_valid());
104                         return (bool)::FLAC__stream_encoder_set_loose_mid_side_stereo(encoder_, value);
105                 }
106
107                 bool Stream::set_channels(unsigned value)
108                 {
109                         FLAC__ASSERT(is_valid());
110                         return (bool)::FLAC__stream_encoder_set_channels(encoder_, value);
111                 }
112
113                 bool Stream::set_bits_per_sample(unsigned value)
114                 {
115                         FLAC__ASSERT(is_valid());
116                         return (bool)::FLAC__stream_encoder_set_bits_per_sample(encoder_, value);
117                 }
118
119                 bool Stream::set_sample_rate(unsigned value)
120                 {
121                         FLAC__ASSERT(is_valid());
122                         return (bool)::FLAC__stream_encoder_set_sample_rate(encoder_, value);
123                 }
124
125                 bool Stream::set_blocksize(unsigned value)
126                 {
127                         FLAC__ASSERT(is_valid());
128                         return (bool)::FLAC__stream_encoder_set_blocksize(encoder_, value);
129                 }
130
131                 bool Stream::set_apodization(const char *specification)
132                 {
133                         FLAC__ASSERT(is_valid());
134                         return (bool)::FLAC__stream_encoder_set_apodization(encoder_, specification);
135                 }
136
137                 bool Stream::set_max_lpc_order(unsigned value)
138                 {
139                         FLAC__ASSERT(is_valid());
140                         return (bool)::FLAC__stream_encoder_set_max_lpc_order(encoder_, value);
141                 }
142
143                 bool Stream::set_qlp_coeff_precision(unsigned value)
144                 {
145                         FLAC__ASSERT(is_valid());
146                         return (bool)::FLAC__stream_encoder_set_qlp_coeff_precision(encoder_, value);
147                 }
148
149                 bool Stream::set_do_qlp_coeff_prec_search(bool value)
150                 {
151                         FLAC__ASSERT(is_valid());
152                         return (bool)::FLAC__stream_encoder_set_do_qlp_coeff_prec_search(encoder_, value);
153                 }
154
155                 bool Stream::set_do_escape_coding(bool value)
156                 {
157                         FLAC__ASSERT(is_valid());
158                         return (bool)::FLAC__stream_encoder_set_do_escape_coding(encoder_, value);
159                 }
160
161                 bool Stream::set_do_exhaustive_model_search(bool value)
162                 {
163                         FLAC__ASSERT(is_valid());
164                         return (bool)::FLAC__stream_encoder_set_do_exhaustive_model_search(encoder_, value);
165                 }
166
167                 bool Stream::set_min_residual_partition_order(unsigned value)
168                 {
169                         FLAC__ASSERT(is_valid());
170                         return (bool)::FLAC__stream_encoder_set_min_residual_partition_order(encoder_, value);
171                 }
172
173                 bool Stream::set_max_residual_partition_order(unsigned value)
174                 {
175                         FLAC__ASSERT(is_valid());
176                         return (bool)::FLAC__stream_encoder_set_max_residual_partition_order(encoder_, value);
177                 }
178
179                 bool Stream::set_rice_parameter_search_dist(unsigned value)
180                 {
181                         FLAC__ASSERT(is_valid());
182                         return (bool)::FLAC__stream_encoder_set_rice_parameter_search_dist(encoder_, value);
183                 }
184
185                 bool Stream::set_total_samples_estimate(FLAC__uint64 value)
186                 {
187                         FLAC__ASSERT(is_valid());
188                         return (bool)::FLAC__stream_encoder_set_total_samples_estimate(encoder_, value);
189                 }
190
191                 bool Stream::set_metadata(::FLAC__StreamMetadata **metadata, unsigned num_blocks)
192                 {
193                         FLAC__ASSERT(is_valid());
194                         return (bool)::FLAC__stream_encoder_set_metadata(encoder_, metadata, num_blocks);
195                 }
196
197                 bool Stream::set_metadata(FLAC::Metadata::Prototype **metadata, unsigned num_blocks)
198                 {
199                         FLAC__ASSERT(is_valid());
200 #if (defined _MSC_VER) || (defined __SUNPRO_CC)
201                         // MSVC++ can't handle:
202                         // ::FLAC__StreamMetadata *m[num_blocks];
203                         // so we do this ugly workaround
204                         ::FLAC__StreamMetadata **m = new ::FLAC__StreamMetadata*[num_blocks];
205 #else
206                         ::FLAC__StreamMetadata *m[num_blocks];
207 #endif
208                         for(unsigned i = 0; i < num_blocks; i++) {
209                                 // we can get away with the const_cast since we know the encoder will only correct the is_last flags
210                                 m[i] = const_cast< ::FLAC__StreamMetadata*>((const ::FLAC__StreamMetadata*)metadata[i]);
211                         }
212 #if (defined _MSC_VER) || (defined __SUNPRO_CC)
213                         // complete the hack
214                         const bool ok = (bool)::FLAC__stream_encoder_set_metadata(encoder_, m, num_blocks);
215                         delete [] m;
216                         return ok;
217 #else
218                         return (bool)::FLAC__stream_encoder_set_metadata(encoder_, m, num_blocks);
219 #endif
220                 }
221
222                 Stream::State Stream::get_state() const
223                 {
224                         FLAC__ASSERT(is_valid());
225                         return State(::FLAC__stream_encoder_get_state(encoder_));
226                 }
227
228                 Decoder::Stream::State Stream::get_verify_decoder_state() const
229                 {
230                         FLAC__ASSERT(is_valid());
231                         return Decoder::Stream::State(::FLAC__stream_encoder_get_verify_decoder_state(encoder_));
232                 }
233
234                 void Stream::get_verify_decoder_error_stats(FLAC__uint64 *absolute_sample, unsigned *frame_number, unsigned *channel, unsigned *sample, FLAC__int32 *expected, FLAC__int32 *got)
235                 {
236                         FLAC__ASSERT(is_valid());
237                         ::FLAC__stream_encoder_get_verify_decoder_error_stats(encoder_, absolute_sample, frame_number, channel, sample, expected, got);
238                 }
239
240                 bool Stream::get_verify() const
241                 {
242                         FLAC__ASSERT(is_valid());
243                         return (bool)::FLAC__stream_encoder_get_verify(encoder_);
244                 }
245
246                 bool Stream::get_streamable_subset() const
247                 {
248                         FLAC__ASSERT(is_valid());
249                         return (bool)::FLAC__stream_encoder_get_streamable_subset(encoder_);
250                 }
251
252                 bool Stream::get_do_mid_side_stereo() const
253                 {
254                         FLAC__ASSERT(is_valid());
255                         return (bool)::FLAC__stream_encoder_get_do_mid_side_stereo(encoder_);
256                 }
257
258                 bool Stream::get_loose_mid_side_stereo() const
259                 {
260                         FLAC__ASSERT(is_valid());
261                         return (bool)::FLAC__stream_encoder_get_loose_mid_side_stereo(encoder_);
262                 }
263
264                 unsigned Stream::get_channels() const
265                 {
266                         FLAC__ASSERT(is_valid());
267                         return ::FLAC__stream_encoder_get_channels(encoder_);
268                 }
269
270                 unsigned Stream::get_bits_per_sample() const
271                 {
272                         FLAC__ASSERT(is_valid());
273                         return ::FLAC__stream_encoder_get_bits_per_sample(encoder_);
274                 }
275
276                 unsigned Stream::get_sample_rate() const
277                 {
278                         FLAC__ASSERT(is_valid());
279                         return ::FLAC__stream_encoder_get_sample_rate(encoder_);
280                 }
281
282                 unsigned Stream::get_blocksize() const
283                 {
284                         FLAC__ASSERT(is_valid());
285                         return ::FLAC__stream_encoder_get_blocksize(encoder_);
286                 }
287
288                 unsigned Stream::get_max_lpc_order() const
289                 {
290                         FLAC__ASSERT(is_valid());
291                         return ::FLAC__stream_encoder_get_max_lpc_order(encoder_);
292                 }
293
294                 unsigned Stream::get_qlp_coeff_precision() const
295                 {
296                         FLAC__ASSERT(is_valid());
297                         return ::FLAC__stream_encoder_get_qlp_coeff_precision(encoder_);
298                 }
299
300                 bool Stream::get_do_qlp_coeff_prec_search() const
301                 {
302                         FLAC__ASSERT(is_valid());
303                         return (bool)::FLAC__stream_encoder_get_do_qlp_coeff_prec_search(encoder_);
304                 }
305
306                 bool Stream::get_do_escape_coding() const
307                 {
308                         FLAC__ASSERT(is_valid());
309                         return (bool)::FLAC__stream_encoder_get_do_escape_coding(encoder_);
310                 }
311
312                 bool Stream::get_do_exhaustive_model_search() const
313                 {
314                         FLAC__ASSERT(is_valid());
315                         return (bool)::FLAC__stream_encoder_get_do_exhaustive_model_search(encoder_);
316                 }
317
318                 unsigned Stream::get_min_residual_partition_order() const
319                 {
320                         FLAC__ASSERT(is_valid());
321                         return ::FLAC__stream_encoder_get_min_residual_partition_order(encoder_);
322                 }
323
324                 unsigned Stream::get_max_residual_partition_order() const
325                 {
326                         FLAC__ASSERT(is_valid());
327                         return ::FLAC__stream_encoder_get_max_residual_partition_order(encoder_);
328                 }
329
330                 unsigned Stream::get_rice_parameter_search_dist() const
331                 {
332                         FLAC__ASSERT(is_valid());
333                         return ::FLAC__stream_encoder_get_rice_parameter_search_dist(encoder_);
334                 }
335
336                 FLAC__uint64 Stream::get_total_samples_estimate() const
337                 {
338                         FLAC__ASSERT(is_valid());
339                         return ::FLAC__stream_encoder_get_total_samples_estimate(encoder_);
340                 }
341
342                 ::FLAC__StreamEncoderInitStatus Stream::init()
343                 {
344                         FLAC__ASSERT(is_valid());
345                         return ::FLAC__stream_encoder_init_stream(encoder_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this);
346                 }
347
348                 ::FLAC__StreamEncoderInitStatus Stream::init_ogg()
349                 {
350                         FLAC__ASSERT(is_valid());
351                         return ::FLAC__stream_encoder_init_ogg_stream(encoder_, read_callback_, write_callback_, seek_callback_, tell_callback_, metadata_callback_, /*client_data=*/(void*)this);
352                 }
353
354                 void Stream::finish()
355                 {
356                         FLAC__ASSERT(is_valid());
357                         ::FLAC__stream_encoder_finish(encoder_);
358                 }
359
360                 bool Stream::process(const FLAC__int32 * const buffer[], unsigned samples)
361                 {
362                         FLAC__ASSERT(is_valid());
363                         return (bool)::FLAC__stream_encoder_process(encoder_, buffer, samples);
364                 }
365
366                 bool Stream::process_interleaved(const FLAC__int32 buffer[], unsigned samples)
367                 {
368                         FLAC__ASSERT(is_valid());
369                         return (bool)::FLAC__stream_encoder_process_interleaved(encoder_, buffer, samples);
370                 }
371
372                 ::FLAC__StreamEncoderReadStatus Stream::read_callback(FLAC__byte buffer[], unsigned *bytes)
373                 {
374                         (void)buffer, (void)bytes;
375                         return ::FLAC__STREAM_ENCODER_READ_STATUS_UNSUPPORTED;
376                 }
377
378                 ::FLAC__StreamEncoderSeekStatus Stream::seek_callback(FLAC__uint64 absolute_byte_offset)
379                 {
380                         (void)absolute_byte_offset;
381                         return ::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
382                 }
383
384                 ::FLAC__StreamEncoderTellStatus Stream::tell_callback(FLAC__uint64 *absolute_byte_offset)
385                 {
386                         (void)absolute_byte_offset;
387                         return ::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
388                 }
389
390                 void Stream::metadata_callback(const ::FLAC__StreamMetadata *metadata)
391                 {
392                         (void)metadata;
393                 }
394
395                 ::FLAC__StreamEncoderReadStatus Stream::read_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__byte buffer[], unsigned *bytes, void *client_data)
396                 {
397                         (void)encoder;
398                         FLAC__ASSERT(0 != client_data);
399                         Stream *instance = reinterpret_cast<Stream *>(client_data);
400                         FLAC__ASSERT(0 != instance);
401                         return instance->read_callback(buffer, bytes);
402                 }
403
404                 ::FLAC__StreamEncoderWriteStatus Stream::write_callback_(const ::FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
405                 {
406                         (void)encoder;
407                         FLAC__ASSERT(0 != client_data);
408                         Stream *instance = reinterpret_cast<Stream *>(client_data);
409                         FLAC__ASSERT(0 != instance);
410                         return instance->write_callback(buffer, bytes, samples, current_frame);
411                 }
412
413                 ::FLAC__StreamEncoderSeekStatus Stream::seek_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 absolute_byte_offset, void *client_data)
414                 {
415                         (void)encoder;
416                         FLAC__ASSERT(0 != client_data);
417                         Stream *instance = reinterpret_cast<Stream *>(client_data);
418                         FLAC__ASSERT(0 != instance);
419                         return instance->seek_callback(absolute_byte_offset);
420                 }
421
422                 ::FLAC__StreamEncoderTellStatus Stream::tell_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
423                 {
424                         (void)encoder;
425                         FLAC__ASSERT(0 != client_data);
426                         Stream *instance = reinterpret_cast<Stream *>(client_data);
427                         FLAC__ASSERT(0 != instance);
428                         return instance->tell_callback(absolute_byte_offset);
429                 }
430
431                 void Stream::metadata_callback_(const ::FLAC__StreamEncoder *encoder, const ::FLAC__StreamMetadata *metadata, void *client_data)
432                 {
433                         (void)encoder;
434                         FLAC__ASSERT(0 != client_data);
435                         Stream *instance = reinterpret_cast<Stream *>(client_data);
436                         FLAC__ASSERT(0 != instance);
437                         instance->metadata_callback(metadata);
438                 }
439
440                 // ------------------------------------------------------------
441                 //
442                 // File
443                 //
444                 // ------------------------------------------------------------
445
446                 File::File():
447                         Stream()
448                 { }
449
450                 File::~File()
451                 {
452                 }
453
454                 ::FLAC__StreamEncoderInitStatus File::init(FILE *file)
455                 {
456                         FLAC__ASSERT(is_valid());
457                         return ::FLAC__stream_encoder_init_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this);
458                 }
459
460                 ::FLAC__StreamEncoderInitStatus File::init(const char *filename)
461                 {
462                         FLAC__ASSERT(is_valid());
463                         return ::FLAC__stream_encoder_init_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this);
464                 }
465
466                 ::FLAC__StreamEncoderInitStatus File::init(const std::string &filename)
467                 {
468                         return init(filename.c_str());
469                 }
470
471                 ::FLAC__StreamEncoderInitStatus File::init_ogg(FILE *file)
472                 {
473                         FLAC__ASSERT(is_valid());
474                         return ::FLAC__stream_encoder_init_ogg_FILE(encoder_, file, progress_callback_, /*client_data=*/(void*)this);
475                 }
476
477                 ::FLAC__StreamEncoderInitStatus File::init_ogg(const char *filename)
478                 {
479                         FLAC__ASSERT(is_valid());
480                         return ::FLAC__stream_encoder_init_ogg_file(encoder_, filename, progress_callback_, /*client_data=*/(void*)this);
481                 }
482
483                 ::FLAC__StreamEncoderInitStatus File::init_ogg(const std::string &filename)
484                 {
485                         return init_ogg(filename.c_str());
486                 }
487
488                 // This is a dummy to satisfy the pure virtual from Stream; the
489                 // read callback will never be called since we are initializing
490                 // with FLAC__stream_decoder_init_FILE() or
491                 // FLAC__stream_decoder_init_file() and those supply the read
492                 // callback internally.
493                 ::FLAC__StreamEncoderWriteStatus File::write_callback(const FLAC__byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame)
494                 {
495                         (void)buffer, (void)bytes, (void)samples, (void)current_frame;
496                         FLAC__ASSERT(false);
497                         return ::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR; // double protection
498                 }
499
500                 void File::progress_callback(FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate)
501                 {
502                         (void)bytes_written, (void)samples_written, (void)frames_written, (void)total_frames_estimate;
503                 }
504
505                 void File::progress_callback_(const ::FLAC__StreamEncoder *encoder, FLAC__uint64 bytes_written, FLAC__uint64 samples_written, unsigned frames_written, unsigned total_frames_estimate, void *client_data)
506                 {
507                         (void)encoder;
508                         FLAC__ASSERT(0 != client_data);
509                         File *instance = reinterpret_cast<File *>(client_data);
510                         FLAC__ASSERT(0 != instance);
511                         instance->progress_callback(bytes_written, samples_written, frames_written, total_frames_estimate);
512                 }
513
514         }
515 }