Should remove remaining chaining glitches by increasing the overlap
[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
47 #define MAX_CHANNELS 8
48
49 #define LPC_PADDING 120
50
51 /* Allow up to 2 seconds for delayed decision. */
52 #define MAX_LOOKAHEAD 96000
53 /* We can't have a circular buffer (because of delayed decision), so let's not copy too often. */
54 #define BUFFER_EXTRA 24000
55
56 #define BUFFER_SAMPLES (MAX_LOOKAHEAD + BUFFER_EXTRA)
57
58 #define MIN(a,b) ((a) < (b) ? (a) : (b))
59 #define MAX(a,b) ((a) > (b) ? (a) : (b))
60
61 #define MAX_PACKET_SIZE (1276*8)
62
63 static int oe_write_page(ogg_page *page, OpusEncCallbacks *cb, void *user_data)
64 {
65    int err;
66    err = cb->write(user_data, page->header, page->header_len);
67    if (err) return -1;
68    err = cb->write(user_data, page->body, page->body_len);
69    if (err) return -1;
70    return page->header_len+page->body_len;
71 }
72
73 struct StdioObject {
74   FILE *file;
75 };
76
77 typedef struct EncStream EncStream;
78
79 struct EncStream {
80   void *user_data;
81   ogg_stream_state os;
82   int serialno_is_set;
83   int serialno;
84   int stream_is_init;
85   int packetno;
86   char *comment;
87   int comment_length;
88   int seen_file_icons;
89   int close_at_end;
90   int header_is_frozen;
91   ogg_int64_t end_granule;
92   ogg_int64_t granule_offset;
93   EncStream *next;
94 };
95
96 struct OggOpusEnc {
97   OpusMSEncoder *st;
98   int rate;
99   int channels;
100   float *buffer;
101   int buffer_start;
102   int buffer_end;
103   SpeexResamplerState *re;
104   int frame_size;
105   int decision_delay;
106   int max_ogg_delay;
107   int global_granule_offset;
108   ogg_int64_t curr_granule;
109   ogg_int64_t write_granule;
110   ogg_int64_t last_page_granule;
111   unsigned char *chaining_keyframe;
112   int chaining_keyframe_length;
113   OpusEncCallbacks callbacks;
114   OpusHeader header;
115   int comment_padding;
116   EncStream *streams;
117   EncStream *last_stream;
118 };
119
120 static int oe_flush_page(OggOpusEnc *enc) {
121   ogg_page og;
122   int ret;
123   int written = 0;
124   while ( (ret = ogg_stream_flush(&enc->streams->os, &og)) ) {
125     if (!ret) break;
126     ret = oe_write_page(&og, &enc->callbacks, enc->streams->user_data);
127     if (ret == -1) {
128       return -1;
129     }
130     written += ret;
131   }
132   return written;
133 }
134
135 int stdio_write(void *user_data, const unsigned char *ptr, int len) {
136   struct StdioObject *obj = (struct StdioObject*)user_data;
137   return fwrite(ptr, 1, len, obj->file) != (size_t)len;
138 }
139
140 int stdio_close(void *user_data) {
141   struct StdioObject *obj = (struct StdioObject*)user_data;
142   int ret = fclose(obj->file);
143   free(obj);
144   return ret;
145 }
146
147 static const OpusEncCallbacks stdio_callbacks = {
148   stdio_write,
149   stdio_close
150 };
151
152 /* Create a new OggOpus file. */
153 OggOpusEnc *ope_create_file(const char *path, int rate, int channels, int family, int *error) {
154   OggOpusEnc *enc;
155   struct StdioObject *obj;
156   obj = malloc(sizeof(*obj));
157   enc = ope_create_callbacks(&stdio_callbacks, obj, rate, channels, family, error);
158   if (enc == NULL || (error && *error)) {
159     return NULL;
160   }
161   obj->file = fopen(path, "wb");
162   if (!obj->file) {
163     if (error) *error = OPE_CANNOT_OPEN;
164     /* FIXME: Destroy the encoder properly. */
165     free(obj);
166     return NULL;
167   }
168   return enc;
169 }
170
171 EncStream *stream_create() {
172   EncStream *stream;
173   stream = malloc(sizeof(*stream));
174   if (!stream) return NULL;
175   stream->next = NULL;
176   stream->close_at_end = 1;
177   stream->serialno_is_set = 0;
178   stream->seen_file_icons = 0;
179   stream->stream_is_init = 0;
180   stream->header_is_frozen = 0;
181   stream->granule_offset = 0;
182   stream->comment = NULL;
183   comment_init(&stream->comment, &stream->comment_length, opus_get_version_string());
184   if (!stream->comment) goto fail;
185   {
186     char encoder_string[1024];
187     snprintf(encoder_string, sizeof(encoder_string), "%s version %s", PACKAGE_NAME, PACKAGE_VERSION);
188     comment_add(&stream->comment, &stream->comment_length, "ENCODER", encoder_string);
189   }
190   return stream;
191 fail:
192   if (stream->comment) free(stream->comment);
193   free(stream);
194   return NULL;
195 }
196
197 static void stream_destroy(EncStream *stream) {
198   if (stream->comment) free(stream->comment);
199   if (stream->stream_is_init) ogg_stream_clear(&stream->os);
200   free(stream);
201 }
202
203 /* Create a new OggOpus file (callback-based). */
204 OggOpusEnc *ope_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data,
205     int rate, int channels, int family, int *error) {
206   OpusMSEncoder *st=NULL;
207   OggOpusEnc *enc=NULL;
208   int ret;
209   if (family != 0 && family != 1 && family != 255) {
210     if (error) *error = OPE_UNIMPLEMENTED;
211     return NULL;
212   }
213   if (channels <= 0 || channels > 255) {
214     if (error) *error = OPE_BAD_ARG;
215     return NULL;
216   }
217   /* FIXME: Add resampling support. */
218   if (rate <= 0) {
219     if (error) *error = OPE_BAD_ARG;
220     return NULL;
221   }
222
223   if ( (enc = malloc(sizeof(*enc))) == NULL) goto fail;
224   enc->streams = NULL;
225   if ( (enc->streams = stream_create()) == NULL) goto fail;
226   enc->streams->next = NULL;
227   enc->last_stream = enc->streams;
228   enc->rate = rate;
229   enc->channels = channels;
230   enc->frame_size = 960;
231   enc->decision_delay = 96000;
232   enc->max_ogg_delay = 48000;
233   enc->chaining_keyframe = NULL;
234   enc->chaining_keyframe_length = -1;
235   enc->comment_padding = 512;
236   enc->header.channels=channels;
237   enc->header.channel_mapping=family;
238   enc->header.input_sample_rate=rate;
239   enc->header.gain=0;
240   st=opus_multistream_surround_encoder_create(48000, channels, enc->header.channel_mapping,
241       &enc->header.nb_streams, &enc->header.nb_coupled,
242       enc->header.stream_map, OPUS_APPLICATION_AUDIO, &ret);
243   if (! (ret == OPUS_OK && st != NULL) ) {
244     goto fail;
245   }
246   if (rate != 48000) {
247     enc->re = speex_resampler_init(channels, rate, 48000, 5, NULL);
248     if (enc->re == NULL) goto fail;
249     speex_resampler_skip_zeros(enc->re);
250   } else {
251     enc->re = NULL;
252   }
253   opus_multistream_encoder_ctl(st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
254   {
255     opus_int32 tmp;
256     int ret;
257     ret = opus_multistream_encoder_ctl(st, OPUS_GET_LOOKAHEAD(&tmp));
258     if (ret == OPUS_OK) enc->header.preskip = tmp;
259     else enc->header.preskip = 0;
260     enc->global_granule_offset = enc->header.preskip;
261   }
262   enc->curr_granule = 0;
263   enc->write_granule = 0;
264   enc->last_page_granule = 0;
265   if ( (enc->buffer = malloc(sizeof(*enc->buffer)*BUFFER_SAMPLES*channels)) == NULL) goto fail;
266   enc->buffer_start = enc->buffer_end = 0;
267   enc->st = st;
268   enc->callbacks = *callbacks;
269   enc->streams->user_data = user_data;
270   if (error) *error = OPE_OK;
271   return enc;
272 fail:
273   if (enc) {
274     free(enc);
275     if (enc->buffer) free(enc->buffer);
276     if (enc->streams) stream_destroy(enc->streams);
277   }
278   if (st) {
279     opus_multistream_encoder_destroy(st);
280   }
281   if (error) *error = OPE_INTERNAL_ERROR;
282   return NULL;
283 }
284
285 static void init_stream(OggOpusEnc *enc) {
286   assert(!enc->streams->stream_is_init);
287   if (!enc->streams->serialno_is_set) {
288     enc->streams->serialno = rand();
289   }
290
291   if (ogg_stream_init(&enc->streams->os, enc->streams->serialno) == -1) {
292     assert(0);
293     /* FIXME: How the hell do we handle that? */
294   }
295   comment_pad(&enc->streams->comment, &enc->streams->comment_length, enc->comment_padding);
296
297   /*Write header*/
298   {
299     ogg_packet op;
300     /*The Identification Header is 19 bytes, plus a Channel Mapping Table for
301       mapping families other than 0. The Channel Mapping Table is 2 bytes +
302       1 byte per channel. Because the maximum number of channels is 255, the
303       maximum size of this header is 19 + 2 + 255 = 276 bytes.*/
304     unsigned char header_data[276];
305     int packet_size = opus_header_to_packet(&enc->header, header_data, sizeof(header_data));
306     op.packet=header_data;
307     op.bytes=packet_size;
308     op.b_o_s=1;
309     op.e_o_s=0;
310     op.granulepos=0;
311     op.packetno=0;
312     ogg_stream_packetin(&enc->streams->os, &op);
313     oe_flush_page(enc);
314
315     op.packet = (unsigned char *)enc->streams->comment;
316     op.bytes = enc->streams->comment_length;
317     op.b_o_s = 0;
318     op.e_o_s = 0;
319     op.granulepos = 0;
320     op.packetno = 1;
321     ogg_stream_packetin(&enc->streams->os, &op);
322     oe_flush_page(enc);
323   }
324   enc->streams->stream_is_init = 1;
325   enc->streams->packetno = 2;
326 }
327
328 static void shift_buffer(OggOpusEnc *enc) {
329     memmove(enc->buffer, &enc->buffer[enc->channels*enc->buffer_start], enc->channels*(enc->buffer_end-enc->buffer_start)*sizeof(*enc->buffer));
330     enc->buffer_end -= enc->buffer_start;
331     enc->buffer_start = 0;
332 }
333
334 static void encode_buffer(OggOpusEnc *enc) {
335   /* Round up when converting the granule pos because the decoder will round down. */
336   ogg_int64_t end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
337   while (enc->buffer_end-enc->buffer_start > enc->frame_size + enc->decision_delay) {
338     int cont;
339     opus_int32 pred;
340     int flush_needed;
341     ogg_packet op;
342     ogg_page og;
343     int nbBytes;
344     unsigned char packet[MAX_PACKET_SIZE];
345     int is_keyframe=0;
346     opus_multistream_encoder_ctl(enc->st, OPUS_GET_PREDICTION_DISABLED(&pred));
347     /* FIXME: a frame that follows a keyframe generally doesn't need to be a keyframe
348        unless there's two consecutive stream boundaries. */
349     if (enc->curr_granule + 2*enc->frame_size>= end_granule48k && enc->streams->next) {
350       opus_multistream_encoder_ctl(enc->st, OPUS_SET_PREDICTION_DISABLED(1));
351       is_keyframe = 1;
352     }
353     nbBytes = opus_multistream_encode_float(enc->st, &enc->buffer[enc->channels*enc->buffer_start],
354         enc->buffer_end-enc->buffer_start, packet, MAX_PACKET_SIZE);
355     /* FIXME: How do we handle failure here. */
356     opus_multistream_encoder_ctl(enc->st, OPUS_SET_PREDICTION_DISABLED(pred));
357     assert(nbBytes > 0);
358     enc->curr_granule += enc->frame_size;
359     op.packet=packet;
360     op.bytes=nbBytes;
361     op.b_o_s=0;
362     op.packetno=enc->streams->packetno++;
363     do {
364       op.granulepos=enc->curr_granule-enc->streams->granule_offset;
365       op.e_o_s=enc->curr_granule >= end_granule48k;
366       cont = 0;
367       if (op.e_o_s) op.granulepos=end_granule48k-enc->streams->granule_offset;
368       ogg_stream_packetin(&enc->streams->os, &op);
369       /* FIXME: Also flush on too many segments. */
370       flush_needed = op.e_o_s || enc->curr_granule - enc->last_page_granule > enc->max_ogg_delay;
371       if (flush_needed) {
372         while (ogg_stream_flush_fill(&enc->streams->os, &og, 255*255)) {
373           if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
374           int ret = oe_write_page(&og, &enc->callbacks, enc->streams->user_data);
375           /* FIXME: what do we do if this fails? */
376           assert(ret != -1);
377         }
378       } else {
379         while (ogg_stream_pageout_fill(&enc->streams->os, &og, 255*255)) {
380           if (ogg_page_packets(&og) != 0) enc->last_page_granule = ogg_page_granulepos(&og) + enc->streams->granule_offset;
381           int ret = oe_write_page(&og, &enc->callbacks, enc->streams->user_data);
382           /* FIXME: what do we do if this fails? */
383           assert(ret != -1);
384         }
385       }
386       if (op.e_o_s) {
387         EncStream *tmp;
388         tmp = enc->streams->next;
389         if (enc->streams->close_at_end) enc->callbacks.close(enc->streams->user_data);
390         stream_destroy(enc->streams);
391         enc->streams = tmp;
392         if (!tmp) enc->last_stream = NULL;
393         if (enc->last_stream == NULL) return;
394         /* We're done with this stream, start the next one. */
395         enc->header.preskip = end_granule48k + enc->frame_size - enc->curr_granule;
396         enc->streams->granule_offset = enc->curr_granule - enc->frame_size;
397         if (enc->chaining_keyframe) {
398           enc->header.preskip += enc->frame_size;
399           enc->streams->granule_offset -= enc->frame_size;
400         }
401         init_stream(enc);
402         if (enc->chaining_keyframe) {
403           ogg_packet op2;
404           op2.packet = enc->chaining_keyframe;
405           op2.bytes = enc->chaining_keyframe_length;
406           op2.b_o_s = 0;
407           op2.e_o_s = 0;
408           op2.packetno=enc->streams->packetno++;
409           op2.granulepos=enc->curr_granule - enc->streams->granule_offset - enc->frame_size;
410           ogg_stream_packetin(&enc->streams->os, &op2);
411         }
412         end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
413         cont = 1;
414       }
415     } while (cont);
416     if (enc->chaining_keyframe) free(enc->chaining_keyframe);
417     if (is_keyframe) {
418       enc->chaining_keyframe = malloc(nbBytes);
419       enc->chaining_keyframe_length = nbBytes;
420       memcpy(enc->chaining_keyframe, packet, nbBytes);
421     } else {
422       enc->chaining_keyframe = NULL;
423       enc->chaining_keyframe_length = -1;
424     }
425     enc->buffer_start += enc->frame_size;
426   }
427   /* If we've reached the end of the buffer, move everything back to the front. */
428   if (enc->buffer_end == BUFFER_SAMPLES) {
429     shift_buffer(enc);
430   }
431   /* This function must never leave the buffer full. */
432   assert(enc->buffer_end < BUFFER_SAMPLES);
433 }
434
435 /* Add/encode any number of float samples to the file. */
436 int ope_write_float(OggOpusEnc *enc, const float *pcm, int samples_per_channel) {
437   int channels = enc->channels;
438   enc->last_stream->header_is_frozen = 1;
439   if (!enc->streams->stream_is_init) init_stream(enc);
440   if (samples_per_channel < 0) return OPE_BAD_ARG;
441   enc->write_granule += samples_per_channel;
442   enc->last_stream->end_granule = enc->write_granule;
443   do {
444     int i;
445     spx_uint32_t in_samples, out_samples;
446     out_samples = BUFFER_SAMPLES-enc->buffer_end;
447     if (enc->re != NULL) {
448       in_samples = samples_per_channel;
449       speex_resampler_process_interleaved_float(enc->re, pcm, &in_samples, &enc->buffer[channels*enc->buffer_end], &out_samples);
450     } else {
451       int curr;
452       curr = MIN((spx_uint32_t)samples_per_channel, out_samples);
453       for (i=0;i<channels*curr;i++) {
454       enc->buffer[channels*enc->buffer_end+i] = pcm[i];
455       }
456       in_samples = out_samples = curr;
457     }
458     enc->buffer_end += out_samples;
459     pcm += in_samples*channels;
460     samples_per_channel -= in_samples;
461     encode_buffer(enc);
462   } while (samples_per_channel > 0);
463   return OPE_OK;
464 }
465
466 #define CONVERT_BUFFER 256
467
468 /* Add/encode any number of int16 samples to the file. */
469 int ope_write(OggOpusEnc *enc, const opus_int16 *pcm, int samples_per_channel) {
470   int channels = enc->channels;
471   enc->last_stream->header_is_frozen = 1;
472   if (!enc->streams->stream_is_init) init_stream(enc);
473   if (samples_per_channel < 0) return OPE_BAD_ARG;
474   enc->write_granule += samples_per_channel;
475   enc->last_stream->end_granule = enc->write_granule;
476   do {
477     int i;
478     spx_uint32_t in_samples, out_samples;
479     out_samples = BUFFER_SAMPLES-enc->buffer_end;
480     if (enc->re != NULL) {
481       float buf[CONVERT_BUFFER*MAX_CHANNELS];
482       in_samples = MIN(CONVERT_BUFFER, samples_per_channel);
483       for (i=0;i<channels*(int)in_samples;i++) {
484         buf[i] = (1.f/32768)*pcm[i];
485       }
486       speex_resampler_process_interleaved_float(enc->re, buf, &in_samples, &enc->buffer[channels*enc->buffer_end], &out_samples);
487     } else {
488       int curr;
489       curr = MIN((spx_uint32_t)samples_per_channel, out_samples);
490       for (i=0;i<channels*curr;i++) {
491         enc->buffer[channels*enc->buffer_end+i] = (1.f/32768)*pcm[i];
492       }
493       in_samples = out_samples = curr;
494     }
495     enc->buffer_end += out_samples;
496     pcm += in_samples*channels;
497     samples_per_channel -= in_samples;
498     encode_buffer(enc);
499   } while (samples_per_channel > 0);
500   return OPE_OK;
501 }
502
503 static void finalize_all_streams(OggOpusEnc *enc) {
504   /* FIXME: Use a better value. */
505   int pad_samples = 3000;
506   if (!enc->streams->stream_is_init) init_stream(enc);
507   shift_buffer(enc);
508   /* FIXME: Do LPC extension instead. */
509   memset(&enc->buffer[enc->channels*enc->buffer_end], 0, pad_samples*enc->channels);
510   enc->decision_delay = 0;
511   enc->buffer_end += pad_samples;
512   assert(enc->buffer_end <= BUFFER_SAMPLES);
513   encode_buffer(enc);
514   assert(enc->streams == NULL);
515 }
516
517 /* Close/finalize the stream. */
518 int ope_close_and_free(OggOpusEnc *enc) {
519   finalize_all_streams(enc);
520   if (enc->chaining_keyframe) free(enc->chaining_keyframe);
521   free(enc->buffer);
522   opus_multistream_encoder_destroy(enc->st);
523   if (enc->re) speex_resampler_destroy(enc->re);
524   free(enc);
525   return OPE_OK;
526 }
527
528 /* Ends the stream and create a new stream within the same file. */
529 int ope_chain_current(OggOpusEnc *enc) {
530   enc->last_stream->close_at_end = 0;
531   return ope_continue_new_callbacks(enc, enc->last_stream->user_data);
532 }
533
534 /* Ends the stream and create a new file. */
535 int ope_continue_new_file(OggOpusEnc *enc, const char *path) {
536   (void)enc;
537   (void)path;
538   return OPE_UNIMPLEMENTED;
539 }
540
541 /* Ends the stream and create a new file (callback-based). */
542 int ope_continue_new_callbacks(OggOpusEnc *enc, void *user_data) {
543   EncStream *new_stream;
544   assert(enc->streams);
545   assert(enc->last_stream);
546   new_stream = stream_create();
547   if (!new_stream) return OPE_INTERNAL_ERROR;
548   new_stream->user_data = user_data;
549   enc->last_stream->next = new_stream;
550   enc->last_stream = new_stream;
551   return OPE_OK;
552 }
553
554 /* Add a comment to the file (can only be called before encoding samples). */
555 int ope_add_comment(OggOpusEnc *enc, const char *tag, const char *val) {
556   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
557   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
558   if (comment_add(&enc->last_stream->comment, &enc->last_stream->comment_length, tag, val)) return OPE_INTERNAL_ERROR;
559   return OPE_OK;
560 }
561
562 int ope_add_picture(OggOpusEnc *enc, const char *spec) {
563   const char *error_message;
564   char *picture_data;
565   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
566   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
567   picture_data = parse_picture_specification(spec, &error_message, &enc->last_stream->seen_file_icons);
568   if(picture_data==NULL){
569     /* FIXME: return proper errors rather than printing a message. */
570     fprintf(stderr,"Error parsing picture option: %s\n",error_message);
571     return OPE_BAD_ARG;
572   }
573   comment_add(&enc->last_stream->comment, &enc->last_stream->comment_length, "METADATA_BLOCK_PICTURE", picture_data);
574   free(picture_data);
575   return OPE_OK;
576 }
577
578 /* Sets the Opus comment vendor string (optional, defaults to library info). */
579 int ope_set_vendor_string(OggOpusEnc *enc, const char *vendor) {
580   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
581   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
582   (void)vendor;
583   return OPE_UNIMPLEMENTED;
584 }
585
586 int ope_flush_header(OggOpusEnc *enc) {
587   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
588   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
589   else init_stream(enc);
590   return OPE_OK;
591 }
592
593 /* Goes straight to the libopus ctl() functions. */
594 int ope_encoder_ctl(OggOpusEnc *enc, int request, ...) {
595   int ret;
596   va_list ap;
597   va_start(ap, request);
598   switch (request) {
599     case OPUS_SET_APPLICATION_REQUEST:
600     case OPUS_SET_BITRATE_REQUEST:
601     case OPUS_SET_MAX_BANDWIDTH_REQUEST:
602     case OPUS_SET_VBR_REQUEST:
603     case OPUS_SET_BANDWIDTH_REQUEST:
604     case OPUS_SET_COMPLEXITY_REQUEST:
605     case OPUS_SET_INBAND_FEC_REQUEST:
606     case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
607     case OPUS_SET_DTX_REQUEST:
608     case OPUS_SET_VBR_CONSTRAINT_REQUEST:
609     case OPUS_SET_FORCE_CHANNELS_REQUEST:
610     case OPUS_SET_SIGNAL_REQUEST:
611     case OPUS_SET_LSB_DEPTH_REQUEST:
612     case OPUS_SET_PREDICTION_DISABLED_REQUEST:
613 #ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
614     case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
615 #endif
616     {
617       opus_int32 value = va_arg(ap, opus_int32);
618       ret = opus_multistream_encoder_ctl(enc->st, request, value);
619     }
620     break;
621     case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
622     {
623       opus_int32 value = va_arg(ap, opus_int32);
624       int max_supported = OPUS_FRAMESIZE_60_MS;
625 #ifdef OPUS_FRAMESIZE_120_MS
626       max_supported = OPUS_FRAMESIZE_120_MS;
627 #endif
628       if (value < OPUS_FRAMESIZE_2_5_MS || value > max_supported) {
629         ret = OPUS_UNIMPLEMENTED;
630         break;
631       }
632       ret = opus_multistream_encoder_ctl(enc->st, request, value);
633       if (ret == OPUS_OK) {
634         if (value <= OPUS_FRAMESIZE_40_MS)
635           enc->frame_size = 120<<(value-OPUS_FRAMESIZE_2_5_MS);
636         else
637           enc->frame_size = (value-OPUS_FRAMESIZE_2_5_MS-2)*960;
638       }
639     }
640     break;
641     default:
642       ret = OPUS_UNIMPLEMENTED;
643   }
644   va_end(ap);
645   return ret;
646 }
647
648 /* ctl()-type call for the OggOpus layer. */
649 int ope_set_params(OggOpusEnc *enc, int request, ...) {
650   int ret;
651   va_list ap;
652   va_start(ap, request);
653   switch (request) {
654     case OPE_SET_DECISION_DELAY_REQUEST:
655     {
656       opus_int32 value = va_arg(ap, opus_int32);
657       if (value < 0) {
658         ret = OPE_BAD_ARG;
659         break;
660       }
661       enc->decision_delay = value;
662       ret = OPE_OK;
663     }
664     break;
665     case OPE_SET_MUXING_DELAY_REQUEST:
666     {
667       opus_int32 value = va_arg(ap, opus_int32);
668       if (value < 0) {
669         ret = OPE_BAD_ARG;
670         break;
671       }
672       enc->max_ogg_delay = value;
673       ret = OPE_OK;
674     }
675     break;
676     case OPE_SET_COMMENT_PADDING_REQUEST:
677     {
678       opus_int32 value = va_arg(ap, opus_int32);
679       if (value < 0) {
680         ret = OPE_BAD_ARG;
681         break;
682       }
683       enc->comment_padding = value;
684       ret = OPE_OK;
685     }
686     break;
687     case OPE_SET_SERIALNO_REQUEST:
688     {
689       opus_int32 value = va_arg(ap, opus_int32);
690       if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
691       enc->last_stream->serialno = value;
692       enc->last_stream->serialno_is_set = 1;
693       ret = OPE_OK;
694     }
695     break;
696     default:
697       return OPE_UNIMPLEMENTED;
698   }
699   va_end(ap);
700   return ret;
701 }