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