refactor
[libopusenc.git] / src / opusenc.c
1 /* Copyright (C)2002-2017 Jean-Marc Valin
2    Copyright (C)2007-2013 Xiph.Org Foundation
3    Copyright (C)2008-2013 Gregory Maxwell
4    File: opusenc.c
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12
13    - Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16
17    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <stdarg.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <assert.h>
41 #include <opus_multistream.h>
42 #include "opusenc.h"
43 #include "opus_header.h"
44 #include "speex_resampler.h"
45 #include "picture.h"
46 #include "ogg_packer.h"
47
48 #define MAX_CHANNELS 8
49
50 #define LPC_PADDING 120
51
52 /* Allow up to 2 seconds for delayed decision. */
53 #define MAX_LOOKAHEAD 96000
54 /* We can't have a circular buffer (because of delayed decision), so let's not copy too often. */
55 #define BUFFER_EXTRA 24000
56
57 #define BUFFER_SAMPLES (MAX_LOOKAHEAD + BUFFER_EXTRA)
58
59 #define MIN(a,b) ((a) < (b) ? (a) : (b))
60 #define MAX(a,b) ((a) > (b) ? (a) : (b))
61
62 #define MAX_PACKET_SIZE (1276*8)
63
64 struct StdioObject {
65   FILE *file;
66 };
67
68 typedef struct EncStream EncStream;
69
70 struct EncStream {
71   void *user_data;
72   ogg_stream_state os;
73   int serialno_is_set;
74   int serialno;
75   int stream_is_init;
76   int packetno;
77   char *comment;
78   int comment_length;
79   int seen_file_icons;
80   int close_at_end;
81   int header_is_frozen;
82   ogg_int64_t end_granule;
83   ogg_int64_t granule_offset;
84   EncStream *next;
85 };
86
87 struct OggOpusEnc {
88   OpusMSEncoder *st;
89   oggpacker *oggp;
90   int rate;
91   int channels;
92   float *buffer;
93   int buffer_start;
94   int buffer_end;
95   SpeexResamplerState *re;
96   int frame_size;
97   int decision_delay;
98   int max_ogg_delay;
99   int global_granule_offset;
100   ogg_int64_t curr_granule;
101   ogg_int64_t write_granule;
102   ogg_int64_t last_page_granule;
103   unsigned char *chaining_keyframe;
104   int chaining_keyframe_length;
105   OpusEncCallbacks callbacks;
106   ope_packet_func packet_callback;
107   ope_page_func page_callback;
108   OpusHeader header;
109   int comment_padding;
110   EncStream *streams;
111   EncStream *last_stream;
112 };
113
114 static int oe_write_page(OggOpusEnc *enc, ogg_page *page, void *user_data)
115 {
116   int length;
117   int err;
118   err = enc->callbacks.write(user_data, page->header, page->header_len);
119   if (err) return -1;
120   err = enc->callbacks.write(user_data, page->body, page->body_len);
121   if (err) return -1;
122   length = page->header_len+page->body_len;
123   if (enc->page_callback) enc->page_callback(user_data, length, 0);
124   return length;
125 }
126
127 static int oe_flush_page(OggOpusEnc *enc) {
128   ogg_page og;
129   int ret;
130   int written = 0;
131
132   oggp_flush_page(enc->oggp);
133   {
134     unsigned char *page;
135     int len;
136     while (oggp_get_next_page(enc->oggp, &page, &len)) {
137       fwrite(page, 1, len, stdout);
138       fflush(stdout);
139     }
140   }
141
142   while ( (ret = ogg_stream_flush_fill(&enc->streams->os, &og, 255*255))) {
143     if (!ret) break;
144     if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
145     ret = oe_write_page(enc, &og, enc->streams->user_data);
146     if (ret == -1) {
147       return -1;
148     }
149     written += ret;
150   }
151   return written;
152 }
153
154 int stdio_write(void *user_data, const unsigned char *ptr, int len) {
155   struct StdioObject *obj = (struct StdioObject*)user_data;
156   return fwrite(ptr, 1, len, obj->file) != (size_t)len;
157 }
158
159 int stdio_close(void *user_data) {
160   struct StdioObject *obj = (struct StdioObject*)user_data;
161   int ret = fclose(obj->file);
162   free(obj);
163   return ret;
164 }
165
166 static const OpusEncCallbacks stdio_callbacks = {
167   stdio_write,
168   stdio_close
169 };
170
171 /* Create a new OggOpus file. */
172 OggOpusEnc *ope_create_file(const char *path, int rate, int channels, int family, int *error) {
173   OggOpusEnc *enc;
174   struct StdioObject *obj;
175   obj = malloc(sizeof(*obj));
176   enc = ope_create_callbacks(&stdio_callbacks, obj, rate, channels, family, error);
177   if (enc == NULL || (error && *error)) {
178     return NULL;
179   }
180   obj->file = fopen(path, "wb");
181   if (!obj->file) {
182     if (error) *error = OPE_CANNOT_OPEN;
183     /* FIXME: Destroy the encoder properly. */
184     free(obj);
185     return NULL;
186   }
187   return enc;
188 }
189
190 EncStream *stream_create() {
191   EncStream *stream;
192   stream = malloc(sizeof(*stream));
193   if (!stream) return NULL;
194   stream->next = NULL;
195   stream->close_at_end = 1;
196   stream->serialno_is_set = 0;
197   stream->seen_file_icons = 0;
198   stream->stream_is_init = 0;
199   stream->header_is_frozen = 0;
200   stream->granule_offset = 0;
201   stream->comment = NULL;
202   comment_init(&stream->comment, &stream->comment_length, opus_get_version_string());
203   if (!stream->comment) goto fail;
204   {
205     char encoder_string[1024];
206     snprintf(encoder_string, sizeof(encoder_string), "%s version %s", PACKAGE_NAME, PACKAGE_VERSION);
207     comment_add(&stream->comment, &stream->comment_length, "ENCODER", encoder_string);
208   }
209   return stream;
210 fail:
211   if (stream->comment) free(stream->comment);
212   free(stream);
213   return NULL;
214 }
215
216 static void stream_destroy(EncStream *stream) {
217   if (stream->comment) free(stream->comment);
218   if (stream->stream_is_init) ogg_stream_clear(&stream->os);
219   free(stream);
220 }
221
222 /* Create a new OggOpus file (callback-based). */
223 OggOpusEnc *ope_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data,
224     int rate, int channels, int family, int *error) {
225   OpusMSEncoder *st=NULL;
226   OggOpusEnc *enc=NULL;
227   int ret;
228   if (family != 0 && family != 1 && family != 255) {
229     if (error) *error = OPE_UNIMPLEMENTED;
230     return NULL;
231   }
232   if (channels <= 0 || channels > 255) {
233     if (error) *error = OPE_BAD_ARG;
234     return NULL;
235   }
236   /* FIXME: Add resampling support. */
237   if (rate <= 0) {
238     if (error) *error = OPE_BAD_ARG;
239     return NULL;
240   }
241
242   if ( (enc = malloc(sizeof(*enc))) == NULL) goto fail;
243   enc->streams = NULL;
244   if ( (enc->streams = stream_create()) == NULL) goto fail;
245   enc->streams->next = NULL;
246   enc->last_stream = enc->streams;
247   enc->packet_callback = NULL;
248   enc->page_callback = NULL;
249   enc->rate = rate;
250   enc->channels = channels;
251   enc->frame_size = 960;
252   enc->decision_delay = 96000;
253   enc->max_ogg_delay = 48000;
254   enc->chaining_keyframe = NULL;
255   enc->chaining_keyframe_length = -1;
256   enc->comment_padding = 512;
257   enc->header.channels=channels;
258   enc->header.channel_mapping=family;
259   enc->header.input_sample_rate=rate;
260   enc->header.gain=0;
261   st=opus_multistream_surround_encoder_create(48000, channels, enc->header.channel_mapping,
262       &enc->header.nb_streams, &enc->header.nb_coupled,
263       enc->header.stream_map, OPUS_APPLICATION_AUDIO, &ret);
264   if (! (ret == OPUS_OK && st != NULL) ) {
265     goto fail;
266   }
267   if (rate != 48000) {
268     enc->re = speex_resampler_init(channels, rate, 48000, 5, NULL);
269     if (enc->re == NULL) goto fail;
270     speex_resampler_skip_zeros(enc->re);
271   } else {
272     enc->re = NULL;
273   }
274   opus_multistream_encoder_ctl(st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
275   {
276     opus_int32 tmp;
277     int ret;
278     ret = opus_multistream_encoder_ctl(st, OPUS_GET_LOOKAHEAD(&tmp));
279     if (ret == OPUS_OK) enc->header.preskip = tmp;
280     else enc->header.preskip = 0;
281     enc->global_granule_offset = enc->header.preskip;
282   }
283   enc->curr_granule = 0;
284   enc->write_granule = 0;
285   enc->last_page_granule = 0;
286   if ( (enc->buffer = malloc(sizeof(*enc->buffer)*BUFFER_SAMPLES*channels)) == NULL) goto fail;
287   enc->buffer_start = enc->buffer_end = 0;
288   enc->st = st;
289   enc->callbacks = *callbacks;
290   enc->streams->user_data = user_data;
291   if (error) *error = OPE_OK;
292   return enc;
293 fail:
294   if (enc) {
295     free(enc);
296     if (enc->buffer) free(enc->buffer);
297     if (enc->streams) stream_destroy(enc->streams);
298   }
299   if (st) {
300     opus_multistream_encoder_destroy(st);
301   }
302   if (error) *error = OPE_ALLOC_FAIL;
303   return NULL;
304 }
305
306 static void init_stream(OggOpusEnc *enc) {
307   assert(!enc->streams->stream_is_init);
308   if (!enc->streams->serialno_is_set) {
309     enc->streams->serialno = rand();
310   }
311
312   enc->oggp = oggp_create(enc->streams->serialno);
313   /* FIXME: How the hell do we handle failure here? */
314
315   if (ogg_stream_init(&enc->streams->os, enc->streams->serialno) == -1) {
316     assert(0);
317     /* FIXME: How the hell do we handle that? */
318   }
319   comment_pad(&enc->streams->comment, &enc->streams->comment_length, enc->comment_padding);
320
321   /*Write header*/
322   {
323     ogg_packet op;
324     /*The Identification Header is 19 bytes, plus a Channel Mapping Table for
325       mapping families other than 0. The Channel Mapping Table is 2 bytes +
326       1 byte per channel. Because the maximum number of channels is 255, the
327       maximum size of this header is 19 + 2 + 255 = 276 bytes.*/
328     unsigned char header_data[276];
329     int packet_size = opus_header_to_packet(&enc->header, header_data, sizeof(header_data));
330     op.packet=header_data;
331     op.bytes=packet_size;
332     op.b_o_s=1;
333     op.e_o_s=0;
334     op.granulepos=0;
335     op.packetno=0;
336     ogg_stream_packetin(&enc->streams->os, &op);
337
338     unsigned char *p;
339     p = oggp_get_packet_buffer(enc->oggp, 276);
340     memcpy(p, header_data, packet_size);
341     oggp_commit_packet(enc->oggp, packet_size, 0, 0);
342
343     oe_flush_page(enc);
344
345     op.packet = (unsigned char *)enc->streams->comment;
346     op.bytes = enc->streams->comment_length;
347     op.b_o_s = 0;
348     op.e_o_s = 0;
349     op.granulepos = 0;
350     op.packetno = 1;
351     ogg_stream_packetin(&enc->streams->os, &op);
352
353     p = oggp_get_packet_buffer(enc->oggp, enc->streams->comment_length);
354     memcpy(p, enc->streams->comment, enc->streams->comment_length);
355     oggp_commit_packet(enc->oggp, enc->streams->comment_length, 0, 0);
356
357     oe_flush_page(enc);
358   }
359   enc->streams->stream_is_init = 1;
360   enc->streams->packetno = 2;
361 }
362
363 static void shift_buffer(OggOpusEnc *enc) {
364     memmove(enc->buffer, &enc->buffer[enc->channels*enc->buffer_start], enc->channels*(enc->buffer_end-enc->buffer_start)*sizeof(*enc->buffer));
365     enc->buffer_end -= enc->buffer_start;
366     enc->buffer_start = 0;
367 }
368
369 static void encode_buffer(OggOpusEnc *enc) {
370   /* Round up when converting the granule pos because the decoder will round down. */
371   ogg_int64_t end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
372   while (enc->buffer_end-enc->buffer_start > enc->frame_size + enc->decision_delay) {
373     int cont;
374     opus_int32 pred;
375     int flush_needed;
376     ogg_packet op;
377     ogg_page og;
378     int nbBytes;
379     unsigned char packet[MAX_PACKET_SIZE];
380     int is_keyframe=0;
381     opus_multistream_encoder_ctl(enc->st, OPUS_GET_PREDICTION_DISABLED(&pred));
382     /* FIXME: a frame that follows a keyframe generally doesn't need to be a keyframe
383        unless there's two consecutive stream boundaries. */
384     if (enc->curr_granule + 2*enc->frame_size>= end_granule48k && enc->streams->next) {
385       opus_multistream_encoder_ctl(enc->st, OPUS_SET_PREDICTION_DISABLED(1));
386       is_keyframe = 1;
387     }
388     nbBytes = opus_multistream_encode_float(enc->st, &enc->buffer[enc->channels*enc->buffer_start],
389         enc->buffer_end-enc->buffer_start, packet, MAX_PACKET_SIZE);
390     /* FIXME: How do we handle failure here. */
391     opus_multistream_encoder_ctl(enc->st, OPUS_SET_PREDICTION_DISABLED(pred));
392     assert(nbBytes > 0);
393     enc->curr_granule += enc->frame_size;
394     op.packet=packet;
395     op.bytes=nbBytes;
396     op.b_o_s=0;
397     op.packetno=enc->streams->packetno++;
398     do {
399       op.granulepos=enc->curr_granule-enc->streams->granule_offset;
400       op.e_o_s=enc->curr_granule >= end_granule48k;
401       cont = 0;
402       if (op.e_o_s) op.granulepos=end_granule48k-enc->streams->granule_offset;
403       ogg_stream_packetin(&enc->streams->os, &op);
404       {
405         unsigned char *p;
406         p = oggp_get_packet_buffer(enc->oggp, MAX_PACKET_SIZE);
407         memcpy(p, packet, nbBytes);
408         oggp_commit_packet(enc->oggp, nbBytes, op.granulepos, op.e_o_s);
409       }
410       if (enc->packet_callback) enc->packet_callback(enc->streams->user_data, op.packet, op.bytes, 0);
411       /* FIXME: Also flush on too many segments. */
412       flush_needed = op.e_o_s || enc->curr_granule - enc->last_page_granule > enc->max_ogg_delay;
413       if (flush_needed) {
414 #if 1
415         oe_flush_page(enc);
416 #else
417         oggp_flush_page(enc->oggp);
418         {
419           unsigned char *page;
420           int len;
421           while (oggp_get_next_page(enc->oggp, &page, &len)) {
422             fwrite(page, 1, len, stdout);
423             fflush(stdout);
424           }
425         }
426         while (ogg_stream_flush_fill(&enc->streams->os, &og, 255*255)) {
427           if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
428           int ret = oe_write_page(enc, &og, enc->streams->user_data);
429           /* FIXME: what do we do if this fails? */
430           assert(ret != -1);
431         }
432 #endif
433       } else {
434         while (ogg_stream_pageout_fill(&enc->streams->os, &og, 255*255)) {
435           if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
436           int ret = oe_write_page(enc, &og, enc->streams->user_data);
437           /* FIXME: what do we do if this fails? */
438           assert(ret != -1);
439         }
440       }
441       if (op.e_o_s) {
442         EncStream *tmp;
443         tmp = enc->streams->next;
444         if (enc->streams->close_at_end) enc->callbacks.close(enc->streams->user_data);
445         stream_destroy(enc->streams);
446         enc->streams = tmp;
447         if (!tmp) enc->last_stream = NULL;
448         if (enc->last_stream == NULL) return;
449         /* We're done with this stream, start the next one. */
450         enc->header.preskip = end_granule48k + enc->frame_size - enc->curr_granule;
451         enc->streams->granule_offset = enc->curr_granule - enc->frame_size;
452         if (enc->chaining_keyframe) {
453           enc->header.preskip += enc->frame_size;
454           enc->streams->granule_offset -= enc->frame_size;
455         }
456         init_stream(enc);
457         if (enc->chaining_keyframe) {
458           ogg_packet op2;
459           op2.packet = enc->chaining_keyframe;
460           op2.bytes = enc->chaining_keyframe_length;
461           op2.b_o_s = 0;
462           op2.e_o_s = 0;
463           op2.packetno=enc->streams->packetno++;
464           op2.granulepos=enc->curr_granule - enc->streams->granule_offset - enc->frame_size;
465           ogg_stream_packetin(&enc->streams->os, &op2);
466           if (enc->packet_callback) enc->packet_callback(enc->streams->user_data, op2.packet, op2.bytes, 0);
467         }
468         end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
469         cont = 1;
470       }
471     } while (cont);
472     if (enc->chaining_keyframe) free(enc->chaining_keyframe);
473     if (is_keyframe) {
474       enc->chaining_keyframe = malloc(nbBytes);
475       enc->chaining_keyframe_length = nbBytes;
476       memcpy(enc->chaining_keyframe, packet, nbBytes);
477     } else {
478       enc->chaining_keyframe = NULL;
479       enc->chaining_keyframe_length = -1;
480     }
481     enc->buffer_start += enc->frame_size;
482   }
483   /* If we've reached the end of the buffer, move everything back to the front. */
484   if (enc->buffer_end == BUFFER_SAMPLES) {
485     shift_buffer(enc);
486   }
487   /* This function must never leave the buffer full. */
488   assert(enc->buffer_end < BUFFER_SAMPLES);
489 }
490
491 /* Add/encode any number of float samples to the file. */
492 int ope_write_float(OggOpusEnc *enc, const float *pcm, int samples_per_channel) {
493   int channels = enc->channels;
494   enc->last_stream->header_is_frozen = 1;
495   if (!enc->streams->stream_is_init) init_stream(enc);
496   if (samples_per_channel < 0) return OPE_BAD_ARG;
497   enc->write_granule += samples_per_channel;
498   enc->last_stream->end_granule = enc->write_granule;
499   do {
500     int i;
501     spx_uint32_t in_samples, out_samples;
502     out_samples = BUFFER_SAMPLES-enc->buffer_end;
503     if (enc->re != NULL) {
504       in_samples = samples_per_channel;
505       speex_resampler_process_interleaved_float(enc->re, pcm, &in_samples, &enc->buffer[channels*enc->buffer_end], &out_samples);
506     } else {
507       int curr;
508       curr = MIN((spx_uint32_t)samples_per_channel, out_samples);
509       for (i=0;i<channels*curr;i++) {
510       enc->buffer[channels*enc->buffer_end+i] = pcm[i];
511       }
512       in_samples = out_samples = curr;
513     }
514     enc->buffer_end += out_samples;
515     pcm += in_samples*channels;
516     samples_per_channel -= in_samples;
517     encode_buffer(enc);
518   } while (samples_per_channel > 0);
519   return OPE_OK;
520 }
521
522 #define CONVERT_BUFFER 256
523
524 /* Add/encode any number of int16 samples to the file. */
525 int ope_write(OggOpusEnc *enc, const opus_int16 *pcm, int samples_per_channel) {
526   int channels = enc->channels;
527   enc->last_stream->header_is_frozen = 1;
528   if (!enc->streams->stream_is_init) init_stream(enc);
529   if (samples_per_channel < 0) return OPE_BAD_ARG;
530   enc->write_granule += samples_per_channel;
531   enc->last_stream->end_granule = enc->write_granule;
532   do {
533     int i;
534     spx_uint32_t in_samples, out_samples;
535     out_samples = BUFFER_SAMPLES-enc->buffer_end;
536     if (enc->re != NULL) {
537       float buf[CONVERT_BUFFER*MAX_CHANNELS];
538       in_samples = MIN(CONVERT_BUFFER, samples_per_channel);
539       for (i=0;i<channels*(int)in_samples;i++) {
540         buf[i] = (1.f/32768)*pcm[i];
541       }
542       speex_resampler_process_interleaved_float(enc->re, buf, &in_samples, &enc->buffer[channels*enc->buffer_end], &out_samples);
543     } else {
544       int curr;
545       curr = MIN((spx_uint32_t)samples_per_channel, out_samples);
546       for (i=0;i<channels*curr;i++) {
547         enc->buffer[channels*enc->buffer_end+i] = (1.f/32768)*pcm[i];
548       }
549       in_samples = out_samples = curr;
550     }
551     enc->buffer_end += out_samples;
552     pcm += in_samples*channels;
553     samples_per_channel -= in_samples;
554     encode_buffer(enc);
555   } while (samples_per_channel > 0);
556   return OPE_OK;
557 }
558
559 static void finalize_all_streams(OggOpusEnc *enc) {
560   /* FIXME: Use a better value. */
561   int pad_samples = 3000;
562   if (!enc->streams->stream_is_init) init_stream(enc);
563   shift_buffer(enc);
564   /* FIXME: Do LPC extension instead. */
565   memset(&enc->buffer[enc->channels*enc->buffer_end], 0, pad_samples*enc->channels);
566   enc->decision_delay = 0;
567   enc->buffer_end += pad_samples;
568   assert(enc->buffer_end <= BUFFER_SAMPLES);
569   encode_buffer(enc);
570   assert(enc->streams == NULL);
571 }
572
573 /* Close/finalize the stream. */
574 int ope_close_and_free(OggOpusEnc *enc) {
575   finalize_all_streams(enc);
576   if (enc->chaining_keyframe) free(enc->chaining_keyframe);
577   free(enc->buffer);
578   opus_multistream_encoder_destroy(enc->st);
579   if (enc->re) speex_resampler_destroy(enc->re);
580   free(enc);
581   return OPE_OK;
582 }
583
584 /* Ends the stream and create a new stream within the same file. */
585 int ope_chain_current(OggOpusEnc *enc) {
586   enc->last_stream->close_at_end = 0;
587   return ope_continue_new_callbacks(enc, enc->last_stream->user_data);
588 }
589
590 /* Ends the stream and create a new file. */
591 int ope_continue_new_file(OggOpusEnc *enc, const char *path) {
592   int ret;
593   struct StdioObject *obj;
594   if (!(obj = malloc(sizeof(*obj)))) return OPE_ALLOC_FAIL;
595   obj->file = fopen(path, "wb");
596   if (!obj->file) {
597     free(obj);
598     /* By trying to open the file first, we can recover if we can't open it. */
599     return OPE_CANNOT_OPEN;
600   }
601   ret = ope_continue_new_callbacks(enc, obj);
602   if (ret == OPE_OK) return ret;
603   fclose(obj->file);
604   free(obj);
605   return ret;
606 }
607
608 /* Ends the stream and create a new file (callback-based). */
609 int ope_continue_new_callbacks(OggOpusEnc *enc, void *user_data) {
610   EncStream *new_stream;
611   assert(enc->streams);
612   assert(enc->last_stream);
613   new_stream = stream_create();
614   if (!new_stream) return OPE_ALLOC_FAIL;
615   new_stream->user_data = user_data;
616   enc->last_stream->next = new_stream;
617   enc->last_stream = new_stream;
618   return OPE_OK;
619 }
620
621 /* Add a comment to the file (can only be called before encoding samples). */
622 int ope_add_comment(OggOpusEnc *enc, const char *tag, const char *val) {
623   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
624   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
625   if (comment_add(&enc->last_stream->comment, &enc->last_stream->comment_length, tag, val)) return OPE_ALLOC_FAIL;
626   return OPE_OK;
627 }
628
629 int ope_add_picture(OggOpusEnc *enc, const char *spec) {
630   const char *error_message;
631   char *picture_data;
632   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
633   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
634   picture_data = parse_picture_specification(spec, &error_message, &enc->last_stream->seen_file_icons);
635   if(picture_data==NULL){
636     /* FIXME: return proper errors rather than printing a message. */
637     fprintf(stderr,"Error parsing picture option: %s\n",error_message);
638     return OPE_BAD_ARG;
639   }
640   comment_add(&enc->last_stream->comment, &enc->last_stream->comment_length, "METADATA_BLOCK_PICTURE", picture_data);
641   free(picture_data);
642   return OPE_OK;
643 }
644
645 /* Sets the Opus comment vendor string (optional, defaults to library info). */
646 int ope_set_vendor_string(OggOpusEnc *enc, const char *vendor) {
647   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
648   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
649   if (comment_replace_vendor_string(&enc->last_stream->comment, &enc->last_stream->comment_length, vendor)) return OPE_ALLOC_FAIL;
650   return OPE_OK;
651 }
652
653 int ope_flush_header(OggOpusEnc *enc) {
654   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
655   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
656   else init_stream(enc);
657   return OPE_OK;
658 }
659
660 /* Goes straight to the libopus ctl() functions. */
661 int ope_encoder_ctl(OggOpusEnc *enc, int request, ...) {
662   int ret;
663   int translate;
664   va_list ap;
665   va_start(ap, request);
666   switch (request) {
667     case OPUS_SET_APPLICATION_REQUEST:
668     case OPUS_SET_BITRATE_REQUEST:
669     case OPUS_SET_MAX_BANDWIDTH_REQUEST:
670     case OPUS_SET_VBR_REQUEST:
671     case OPUS_SET_BANDWIDTH_REQUEST:
672     case OPUS_SET_COMPLEXITY_REQUEST:
673     case OPUS_SET_INBAND_FEC_REQUEST:
674     case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
675     case OPUS_SET_DTX_REQUEST:
676     case OPUS_SET_VBR_CONSTRAINT_REQUEST:
677     case OPUS_SET_FORCE_CHANNELS_REQUEST:
678     case OPUS_SET_SIGNAL_REQUEST:
679     case OPUS_SET_LSB_DEPTH_REQUEST:
680     case OPUS_SET_PREDICTION_DISABLED_REQUEST:
681 #ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
682     case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
683 #endif
684     {
685       opus_int32 value = va_arg(ap, opus_int32);
686       ret = opus_multistream_encoder_ctl(enc->st, request, value);
687     }
688     break;
689     case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
690     {
691       opus_int32 value = va_arg(ap, opus_int32);
692       int max_supported = OPUS_FRAMESIZE_60_MS;
693 #ifdef OPUS_FRAMESIZE_120_MS
694       max_supported = OPUS_FRAMESIZE_120_MS;
695 #endif
696       if (value < OPUS_FRAMESIZE_2_5_MS || value > max_supported) {
697         ret = OPUS_UNIMPLEMENTED;
698         break;
699       }
700       ret = opus_multistream_encoder_ctl(enc->st, request, value);
701       if (ret == OPUS_OK) {
702         if (value <= OPUS_FRAMESIZE_40_MS)
703           enc->frame_size = 120<<(value-OPUS_FRAMESIZE_2_5_MS);
704         else
705           enc->frame_size = (value-OPUS_FRAMESIZE_2_5_MS-2)*960;
706       }
707     }
708     break;
709     case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
710     {
711       opus_int32 stream_id;
712       OpusEncoder **value;
713       stream_id = va_arg(ap, opus_int32);
714       value = va_arg(ap, OpusEncoder**);
715       ret = opus_multistream_encoder_ctl(enc->st, request, stream_id, value);
716     }
717     break;
718
719     /* ****************** libopusenc-specific requests. ********************** */
720     case OPE_SET_DECISION_DELAY_REQUEST:
721     {
722       opus_int32 value = va_arg(ap, opus_int32);
723       if (value < 0) {
724         ret = OPE_BAD_ARG;
725         break;
726       }
727       enc->decision_delay = value;
728       ret = OPE_OK;
729     }
730     break;
731     case OPE_SET_MUXING_DELAY_REQUEST:
732     {
733       opus_int32 value = va_arg(ap, opus_int32);
734       if (value < 0) {
735         ret = OPE_BAD_ARG;
736         break;
737       }
738       enc->max_ogg_delay = value;
739       ret = OPE_OK;
740     }
741     break;
742     case OPE_SET_COMMENT_PADDING_REQUEST:
743     {
744       opus_int32 value = va_arg(ap, opus_int32);
745       if (value < 0) {
746         ret = OPE_BAD_ARG;
747         break;
748       }
749       enc->comment_padding = value;
750       ret = OPE_OK;
751     }
752     break;
753     case OPE_SET_SERIALNO_REQUEST:
754     {
755       opus_int32 value = va_arg(ap, opus_int32);
756       if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
757       enc->last_stream->serialno = value;
758       enc->last_stream->serialno_is_set = 1;
759       ret = OPE_OK;
760     }
761     case OPE_SET_PACKET_CALLBACK_REQUEST:
762     {
763       ope_packet_func value = va_arg(ap, ope_packet_func);
764       enc->packet_callback = value;
765       ret = OPE_OK;
766     }
767     break;
768     case OPE_SET_PAGE_CALLBACK_REQUEST:
769     {
770       ope_page_func value = va_arg(ap, ope_page_func);
771       enc->page_callback = value;
772       ret = OPE_OK;
773     }
774     break;
775     default:
776       return OPE_UNIMPLEMENTED;
777   }
778   va_end(ap);
779   translate = request < 14000 || (ret < 0 && ret >= -10);
780   if (translate) {
781     if (ret == OPUS_BAD_ARG) ret = OPE_BAD_ARG;
782     else if (ret == OPUS_INTERNAL_ERROR) ret = OPE_INTERNAL_ERROR;
783     else if (ret == OPUS_UNIMPLEMENTED) ret = OPE_UNIMPLEMENTED;
784     else if (ret == OPUS_ALLOC_FAIL) ret = OPE_ALLOC_FAIL;
785     else ret = OPE_INTERNAL_ERROR;
786   }
787   assert(ret == 0 || ret < -10);
788   return ret;
789 }