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 <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <assert.h>
39 #include "opusenc.h"
40 #include "opus_header.h"
41 #include "speex_resampler.h"
42 #include "picture.h"
43 #include "ogg_packer.h"
44 #include "unicode_support.h"
45 
46 /* Bump this when we change the ABI. */
47 #define OPE_ABI_VERSION 0
48 
49 #define LPC_PADDING 120
50 #define LPC_ORDER 24
51 #define LPC_INPUT 480
52 /* Make the following constant always equal to 2*cos(M_PI/LPC_PADDING) */
53 #define LPC_GOERTZEL_CONST 1.99931465f
54 
55 /* Allow up to 2 seconds for delayed decision. */
56 #define MAX_LOOKAHEAD 96000
57 /* We can't have a circular buffer (because of delayed decision), so let's not copy too often. */
58 #define BUFFER_EXTRA 24000
59 
60 #define BUFFER_SAMPLES (MAX_LOOKAHEAD + BUFFER_EXTRA)
61 
62 #define MIN(a,b) ((a) < (b) ? (a) : (b))
63 #define MAX(a,b) ((a) > (b) ? (a) : (b))
64 
65 #ifdef _MSC_VER
66 # if (_MSC_VER < 1900)
67 #  define snprintf _snprintf
68 # endif
69 #endif
70 
71 struct StdioObject {
72   FILE *file;
73 };
74 
75 struct OggOpusComments {
76   char *comment;
77   int comment_length;
78   int seen_file_icons;
79 };
80 
81 /* Create a new comments object. The vendor string is optional. */
ope_comments_create()82 OggOpusComments *ope_comments_create() {
83   OggOpusComments *c;
84   const char *libopus_str;
85   char vendor_str[1024];
86   c = malloc(sizeof(*c));
87   if (c == NULL) return NULL;
88   libopus_str = opus_get_version_string();
89   snprintf(vendor_str, sizeof(vendor_str), "%s, %s %s", libopus_str, PACKAGE_NAME, PACKAGE_VERSION);
90   opeint_comment_init(&c->comment, &c->comment_length, vendor_str);
91   c->seen_file_icons = 0;
92   if (c->comment == NULL) {
93     free(c);
94     return NULL;
95   } else {
96     return c;
97   }
98 }
99 
100 /* Create a deep copy of a comments object. */
ope_comments_copy(OggOpusComments * comments)101 OggOpusComments *ope_comments_copy(OggOpusComments *comments) {
102   OggOpusComments *c;
103   c = malloc(sizeof(*c));
104   if (c == NULL) return NULL;
105   memcpy(c, comments, sizeof(*c));
106   c->comment = malloc(comments->comment_length);
107   if (c->comment == NULL) {
108     free(c);
109     return NULL;
110   } else {
111     memcpy(c->comment, comments->comment, comments->comment_length);
112     return c;
113   }
114 }
115 
116 /* Destroys a comments object. */
ope_comments_destroy(OggOpusComments * comments)117 void ope_comments_destroy(OggOpusComments *comments){
118   free(comments->comment);
119   free(comments);
120 }
121 
122 /* Add a comment. */
ope_comments_add(OggOpusComments * comments,const char * tag,const char * val)123 int ope_comments_add(OggOpusComments *comments, const char *tag, const char *val) {
124   if (tag == NULL || val == NULL) return OPE_BAD_ARG;
125   if (strchr(tag, '=')) return OPE_BAD_ARG;
126   if (opeint_comment_add(&comments->comment, &comments->comment_length, tag, val)) return OPE_ALLOC_FAIL;
127   return OPE_OK;
128 }
129 
130 /* Add a comment. */
ope_comments_add_string(OggOpusComments * comments,const char * tag_and_val)131 int ope_comments_add_string(OggOpusComments *comments, const char *tag_and_val) {
132   if (!strchr(tag_and_val, '=')) return OPE_BAD_ARG;
133   if (opeint_comment_add(&comments->comment, &comments->comment_length, NULL, tag_and_val)) return OPE_ALLOC_FAIL;
134   return OPE_OK;
135 }
136 
ope_comments_add_picture(OggOpusComments * comments,const char * filename,int picture_type,const char * description)137 int ope_comments_add_picture(OggOpusComments *comments, const char *filename, int picture_type, const char *description) {
138   char *picture_data;
139   int err;
140   picture_data = opeint_parse_picture_specification(filename, picture_type, description, &err, &comments->seen_file_icons);
141   if (picture_data == NULL || err != OPE_OK){
142     return err;
143   }
144   opeint_comment_add(&comments->comment, &comments->comment_length, "METADATA_BLOCK_PICTURE", picture_data);
145   free(picture_data);
146   return OPE_OK;
147 }
148 
ope_comments_add_picture_from_memory(OggOpusComments * comments,const char * ptr,size_t size,int picture_type,const char * description)149 int ope_comments_add_picture_from_memory(OggOpusComments *comments, const char *ptr, size_t size, int picture_type, const char *description) {
150   char *picture_data;
151   int err;
152   picture_data = opeint_parse_picture_specification_from_memory(ptr, size, picture_type, description, &err, &comments->seen_file_icons);
153   if (picture_data == NULL || err != OPE_OK){
154     return err;
155   }
156   opeint_comment_add(&comments->comment, &comments->comment_length, "METADATA_BLOCK_PICTURE", picture_data);
157   free(picture_data);
158   return OPE_OK;
159 }
160 
161 
162 typedef struct EncStream EncStream;
163 
164 struct EncStream {
165   void *user_data;
166   int serialno_is_set;
167   int serialno;
168   int stream_is_init;
169   int packetno;
170   char *comment;
171   int comment_length;
172   int seen_file_icons;
173   int close_at_end;
174   int header_is_frozen;
175   opus_int64 end_granule;
176   opus_int64 granule_offset;
177   EncStream *next;
178 };
179 
opeint_use_projection(int channel_mapping)180 int opeint_use_projection(int channel_mapping) {
181   if (channel_mapping==3){
182     return 1;
183   }
184   return 0;
185 }
186 
opeint_encoder_surround_init(OpusGenericEncoder * st,int Fs,int channels,int channel_mapping,int * nb_streams,int * nb_coupled,unsigned char * stream_map,int application)187 int opeint_encoder_surround_init(
188     OpusGenericEncoder *st, int Fs, int channels, int channel_mapping,
189     int *nb_streams, int *nb_coupled, unsigned char *stream_map, int application) {
190   int ret;
191 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
192   if(opeint_use_projection(channel_mapping)){
193     int ci;
194     st->pr=opus_projection_ambisonics_encoder_create(Fs, channels,
195         channel_mapping, nb_streams, nb_coupled, application, &ret);
196     for (ci = 0; ci < channels; ci++) {
197       stream_map[ci] = ci;
198     }
199     st->ms=NULL;
200   }
201   else
202 #endif
203   {
204 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
205     st->pr=NULL;
206 #endif
207     st->ms=opus_multistream_surround_encoder_create(Fs, channels,
208         channel_mapping, nb_streams, nb_coupled, stream_map, application, &ret);
209   }
210   return ret;
211 }
212 
opeint_encoder_cleanup(OpusGenericEncoder * st)213 void opeint_encoder_cleanup(OpusGenericEncoder *st) {
214 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
215     if (st->pr) opus_projection_encoder_destroy(st->pr);
216 #endif
217     if (st->ms) opus_multistream_encoder_destroy(st->ms);
218 }
219 
opeint_encoder_init(OpusGenericEncoder * st,opus_int32 Fs,int channels,int streams,int coupled_streams,const unsigned char * mapping,int application)220 int opeint_encoder_init(
221     OpusGenericEncoder *st, opus_int32 Fs, int channels, int streams,
222     int coupled_streams, const unsigned char *mapping, int application) {
223   int ret;
224 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
225   st->pr=NULL;
226 #endif
227   st->ms=opus_multistream_encoder_create(Fs, channels, streams,
228       coupled_streams, mapping, application, &ret);
229   return ret;
230 }
231 
opeint_encode_float(OpusGenericEncoder * st,const float * pcm,int frame_size,unsigned char * data,opus_int32 max_data_bytes)232 int opeint_encode_float(
233     OpusGenericEncoder *st,
234     const float *pcm,
235     int frame_size,
236     unsigned char *data,
237     opus_int32 max_data_bytes) {
238   int ret;
239 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
240   if (st->pr) ret=opus_projection_encode_float(st->pr, pcm, frame_size, data, max_data_bytes);
241   else
242 #endif
243     ret=opus_multistream_encode_float(st->ms, pcm, frame_size, data, max_data_bytes);
244   return ret;
245 }
246 
247 struct OggOpusEnc {
248   OpusGenericEncoder st;
249   oggpacker *oggp;
250   int unrecoverable;
251   int pull_api;
252   int rate;
253   int channels;
254   float *buffer;
255   int buffer_start;
256   int buffer_end;
257   SpeexResamplerState *re;
258   int frame_size;
259   int decision_delay;
260   int max_ogg_delay;
261   int global_granule_offset;
262   opus_int64 curr_granule;
263   opus_int64 write_granule;
264   opus_int64 last_page_granule;
265   int draining;
266   int frame_size_request;
267   float *lpc_buffer;
268   unsigned char *chaining_keyframe;
269   int chaining_keyframe_length;
270   OpusEncCallbacks callbacks;
271   ope_packet_func packet_callback;
272   void *packet_callback_data;
273   OpusHeader header;
274   int comment_padding;
275   EncStream *streams;
276   EncStream *last_stream;
277 };
278 
output_pages(OggOpusEnc * enc)279 static int output_pages(OggOpusEnc *enc) {
280   unsigned char *page;
281   int len;
282   while (oggp_get_next_page(enc->oggp, &page, &len)) {
283     int ret = enc->callbacks.write(enc->streams->user_data, page, len);
284     if (ret) return ret;
285   }
286   return 0;
287 }
oe_flush_page(OggOpusEnc * enc)288 static int oe_flush_page(OggOpusEnc *enc) {
289   oggp_flush_page(enc->oggp);
290   if (!enc->pull_api) return output_pages(enc);
291   return 0;
292 }
293 
stdio_write(void * user_data,const unsigned char * ptr,opus_int32 len)294 static int stdio_write(void *user_data, const unsigned char *ptr, opus_int32 len) {
295   int ret;
296   struct StdioObject *obj = (struct StdioObject*)user_data;
297   ret = fwrite(ptr, 1, len, obj->file) != (size_t)len;
298   return ret;
299 }
300 
stdio_close(void * user_data)301 static int stdio_close(void *user_data) {
302   struct StdioObject *obj = (struct StdioObject*)user_data;
303   int ret = 0;
304   if (obj->file) ret = fclose(obj->file);
305   free(obj);
306   return ret!=0;
307 }
308 
309 static const OpusEncCallbacks stdio_callbacks = {
310   stdio_write,
311   stdio_close
312 };
313 
314 /* Create a new OggOpus file. */
ope_encoder_create_file(const char * path,OggOpusComments * comments,opus_int32 rate,int channels,int family,int * error)315 OggOpusEnc *ope_encoder_create_file(const char *path, OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error) {
316   OggOpusEnc *enc;
317   struct StdioObject *obj;
318   obj = malloc(sizeof(*obj));
319   if (obj == NULL) {
320     if (error) *error = OPE_ALLOC_FAIL;
321     return NULL;
322   }
323   enc = ope_encoder_create_callbacks(&stdio_callbacks, obj, comments, rate, channels, family, error);
324   if (enc == NULL || (error && *error)) {
325     free(obj);
326     return NULL;
327   }
328   obj->file = opeint_fopen(path, "wb");
329   if (!obj->file) {
330     if (error) *error = OPE_CANNOT_OPEN;
331     ope_encoder_destroy(enc);
332     return NULL;
333   }
334   return enc;
335 }
336 
stream_create(OggOpusComments * comments)337 EncStream *stream_create(OggOpusComments *comments) {
338   EncStream *stream;
339   stream = malloc(sizeof(*stream));
340   if (!stream) return NULL;
341   stream->next = NULL;
342   stream->close_at_end = 1;
343   stream->serialno_is_set = 0;
344   stream->stream_is_init = 0;
345   stream->header_is_frozen = 0;
346   stream->granule_offset = 0;
347   stream->comment = malloc(comments->comment_length);
348   if (stream->comment == NULL) goto fail;
349   memcpy(stream->comment, comments->comment, comments->comment_length);
350   stream->comment_length = comments->comment_length;
351   stream->seen_file_icons = comments->seen_file_icons;
352   return stream;
353 fail:
354   if (stream->comment) free(stream->comment);
355   free(stream);
356   return NULL;
357 }
358 
stream_destroy(EncStream * stream)359 static void stream_destroy(EncStream *stream) {
360   if (stream->comment) free(stream->comment);
361   free(stream);
362 }
363 
364 /* Create a new OggOpus file (callback-based). */
ope_encoder_create_callbacks(const OpusEncCallbacks * callbacks,void * user_data,OggOpusComments * comments,opus_int32 rate,int channels,int family,int * error)365 OggOpusEnc *ope_encoder_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data,
366     OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error) {
367   OggOpusEnc *enc=NULL;
368   int ret;
369   if (family != 0 && family != 1 &&
370 #ifdef OPUS_HAVE_OPUS_PROJECTION_H
371       family != 2 && family != 3 &&
372 #endif
373       family != 255 && family != -1) {
374     if (error) {
375       if (family < -1 || family > 255) *error = OPE_BAD_ARG;
376       else *error = OPE_UNIMPLEMENTED;
377     }
378     return NULL;
379   }
380   if (channels <= 0 || channels > 255) {
381     if (error) *error = OPE_BAD_ARG;
382     return NULL;
383   }
384   if (rate <= 0) {
385     if (error) *error = OPE_BAD_ARG;
386     return NULL;
387   }
388   /* Setting the most common failure up-front. */
389   if (error) *error = OPE_ALLOC_FAIL;
390   if ( (enc = malloc(sizeof(*enc))) == NULL) goto fail;
391   enc->buffer = NULL;
392   enc->lpc_buffer = NULL;
393   if ( (enc->streams = stream_create(comments)) == NULL) goto fail;
394   enc->last_stream = enc->streams;
395   enc->oggp = NULL;
396   /* Not initializing anything is an unrecoverable error. */
397   enc->unrecoverable = family == -1 ? OPE_TOO_LATE : 0;
398   enc->pull_api = 0;
399   enc->packet_callback = NULL;
400   enc->rate = rate;
401   enc->channels = channels;
402   enc->frame_size = 960;
403   enc->decision_delay = 96000;
404   enc->max_ogg_delay = 48000;
405   enc->chaining_keyframe = NULL;
406   enc->chaining_keyframe_length = -1;
407   enc->comment_padding = 512;
408   enc->header.channels=channels;
409   enc->header.channel_mapping=family;
410   enc->header.input_sample_rate=rate;
411   enc->header.gain=0;
412   if (family != -1) {
413     ret=opeint_encoder_surround_init(&enc->st, 48000, channels,
414         enc->header.channel_mapping, &enc->header.nb_streams,
415         &enc->header.nb_coupled, enc->header.stream_map,
416         OPUS_APPLICATION_AUDIO);
417     if (! (ret == OPUS_OK) ) {
418       if (ret == OPUS_BAD_ARG) ret = OPE_BAD_ARG;
419       else if (ret == OPUS_INTERNAL_ERROR) ret = OPE_INTERNAL_ERROR;
420       else if (ret == OPUS_UNIMPLEMENTED) ret = OPE_UNIMPLEMENTED;
421       else if (ret == OPUS_ALLOC_FAIL) ret = OPE_ALLOC_FAIL;
422       else ret = OPE_INTERNAL_ERROR;
423       if (error) *error = ret;
424       goto fail;
425     }
426     opeint_encoder_ctl(&enc->st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
427   }
428   if (rate != 48000) {
429     enc->re = speex_resampler_init(channels, rate, 48000, 5, NULL);
430     if (enc->re == NULL) goto fail;
431     speex_resampler_skip_zeros(enc->re);
432   } else {
433     enc->re = NULL;
434   }
435   enc->global_granule_offset = -1;
436   enc->curr_granule = 0;
437   enc->write_granule = 0;
438   enc->last_page_granule = 0;
439   enc->draining = 0;
440   if ( (enc->buffer = malloc(sizeof(*enc->buffer)*BUFFER_SAMPLES*channels)) == NULL) goto fail;
441   if (rate != 48000) {
442     /* Allocate an extra LPC_PADDING samples so we can do the padding in-place. */
443     if ( (enc->lpc_buffer = malloc(sizeof(*enc->lpc_buffer)*(LPC_INPUT+LPC_PADDING)*channels)) == NULL) goto fail;
444     memset(enc->lpc_buffer, 0, sizeof(*enc->lpc_buffer)*LPC_INPUT*channels);
445   }
446   enc->buffer_start = enc->buffer_end = 0;
447   if (callbacks != NULL)
448   {
449     enc->callbacks = *callbacks;
450   }
451   enc->streams->user_data = user_data;
452   if (error) *error = OPE_OK;
453   return enc;
454 fail:
455   if (enc) {
456     opeint_encoder_cleanup(&enc->st);
457     if (enc->buffer) free(enc->buffer);
458     if (enc->streams) stream_destroy(enc->streams);
459     if (enc->lpc_buffer) free(enc->lpc_buffer);
460     free(enc);
461   }
462   return NULL;
463 }
464 
465 /* Create a new OggOpus stream, pulling one page at a time. */
ope_encoder_create_pull(OggOpusComments * comments,opus_int32 rate,int channels,int family,int * error)466 OggOpusEnc *ope_encoder_create_pull(OggOpusComments *comments, opus_int32 rate, int channels, int family, int *error) {
467   OggOpusEnc *enc = ope_encoder_create_callbacks(NULL, NULL, comments, rate, channels, family, error);
468   if (enc) enc->pull_api = 1;
469   return enc;
470 }
471 
ope_encoder_deferred_init_with_mapping(OggOpusEnc * enc,int family,int streams,int coupled_streams,const unsigned char * mapping)472 int ope_encoder_deferred_init_with_mapping(OggOpusEnc *enc, int family, int streams,
473     int coupled_streams, const unsigned char *mapping) {
474   int ret;
475   int i;
476   if (family < 0 || family > 255) return OPE_BAD_ARG;
477   else if (family != 1 &&
478   #ifdef OPUS_HAVE_OPUS_PROJECTION_H
479       family != 2 &&
480   #endif
481       family != 255) return OPE_UNIMPLEMENTED;
482   else if (streams <= 0 || streams>255 || coupled_streams<0 || coupled_streams >= 128 || streams+coupled_streams > 255) return OPE_BAD_ARG;
483   ret=opeint_encoder_init(&enc->st, 48000, enc->channels, streams, coupled_streams, mapping, OPUS_APPLICATION_AUDIO);
484   if (! (ret == OPUS_OK) ) {
485     if (ret == OPUS_BAD_ARG) ret = OPE_BAD_ARG;
486     else if (ret == OPUS_INTERNAL_ERROR) ret = OPE_INTERNAL_ERROR;
487     else if (ret == OPUS_UNIMPLEMENTED) ret = OPE_UNIMPLEMENTED;
488     else if (ret == OPUS_ALLOC_FAIL) ret = OPE_ALLOC_FAIL;
489     else ret = OPE_INTERNAL_ERROR;
490     return ret;
491   }
492   opeint_encoder_ctl(&enc->st, OPUS_SET_EXPERT_FRAME_DURATION(OPUS_FRAMESIZE_20_MS));
493   enc->unrecoverable = 0;
494   enc->header.channel_mapping=family;
495   enc->header.nb_streams = streams;
496   enc->header.nb_coupled = coupled_streams;
497   for (i=0;i<streams+coupled_streams;i++)
498     enc->header.stream_map[i] = mapping[i];
499   return OPE_OK;
500 }
501 
init_stream(OggOpusEnc * enc)502 static void init_stream(OggOpusEnc *enc) {
503   assert(!enc->streams->stream_is_init);
504   if (!enc->streams->serialno_is_set) {
505     enc->streams->serialno = rand();
506   }
507 
508   if (enc->oggp != NULL) oggp_chain(enc->oggp, enc->streams->serialno);
509   else {
510     enc->oggp = oggp_create(enc->streams->serialno);
511     if (enc->oggp == NULL) {
512       enc->unrecoverable = OPE_ALLOC_FAIL;
513       return;
514     }
515     oggp_set_muxing_delay(enc->oggp, enc->max_ogg_delay);
516   }
517   opeint_comment_pad(&enc->streams->comment, &enc->streams->comment_length, enc->comment_padding);
518 
519   /* Get preskip at the last minute (when it can no longer change). */
520   if (enc->global_granule_offset == -1) {
521     opus_int32 tmp;
522     int ret;
523     ret=opeint_encoder_ctl(&enc->st, OPUS_GET_LOOKAHEAD(&tmp));
524     if (ret == OPUS_OK) enc->header.preskip = tmp;
525     else enc->header.preskip = 0;
526     enc->global_granule_offset = enc->header.preskip;
527   }
528   /*Write header*/
529   {
530     int header_size;
531     int ret;
532     int packet_size;
533     unsigned char *p;
534     header_size = opeint_opus_header_get_size(&enc->header);
535     p = oggp_get_packet_buffer(enc->oggp, header_size);
536     packet_size = opeint_opus_header_to_packet(&enc->header, p, header_size, &enc->st);
537     if (enc->packet_callback) enc->packet_callback(enc->packet_callback_data, p, packet_size, 0);
538     oggp_commit_packet(enc->oggp, packet_size, 0, 0);
539     ret = oe_flush_page(enc);
540     if (ret) {
541       enc->unrecoverable = OPE_WRITE_FAIL;
542       return;
543     }
544     p = oggp_get_packet_buffer(enc->oggp, enc->streams->comment_length);
545     memcpy(p, enc->streams->comment, enc->streams->comment_length);
546     if (enc->packet_callback) enc->packet_callback(enc->packet_callback_data, p, enc->streams->comment_length, 0);
547     oggp_commit_packet(enc->oggp, enc->streams->comment_length, 0, 0);
548     ret = oe_flush_page(enc);
549     if (ret) {
550       enc->unrecoverable = OPE_WRITE_FAIL;
551       return;
552     }
553   }
554   enc->streams->stream_is_init = 1;
555   enc->streams->packetno = 2;
556 }
557 
shift_buffer(OggOpusEnc * enc)558 static void shift_buffer(OggOpusEnc *enc) {
559   /* Leaving enough in the buffer to do LPC extension if needed. */
560   if (enc->buffer_start > LPC_INPUT) {
561     memmove(&enc->buffer[0], &enc->buffer[enc->channels*(enc->buffer_start-LPC_INPUT)],
562             enc->channels*(enc->buffer_end-enc->buffer_start+LPC_INPUT)*sizeof(*enc->buffer));
563     enc->buffer_end -= enc->buffer_start-LPC_INPUT;
564     enc->buffer_start = LPC_INPUT;
565   }
566 }
567 
compute_frame_samples(int size_request)568 static int compute_frame_samples(int size_request) {
569   if (size_request <= OPUS_FRAMESIZE_40_MS) return 120<<(size_request-OPUS_FRAMESIZE_2_5_MS);
570   else return (size_request-OPUS_FRAMESIZE_2_5_MS-2)*960;
571 }
572 
encode_buffer(OggOpusEnc * enc)573 static void encode_buffer(OggOpusEnc *enc) {
574   opus_int32 max_packet_size;
575   /* Round up when converting the granule pos because the decoder will round down. */
576   opus_int64 end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
577   max_packet_size = (1277*6+2)*enc->header.nb_streams;
578   while (enc->buffer_end-enc->buffer_start > enc->frame_size + enc->decision_delay) {
579     int cont;
580     int e_o_s;
581     opus_int32 pred;
582     int nbBytes;
583     unsigned char *packet;
584     unsigned char *packet_copy = NULL;
585     int is_keyframe=0;
586     if (enc->unrecoverable) return;
587     opeint_encoder_ctl(&enc->st, OPUS_GET_PREDICTION_DISABLED(&pred));
588     /* FIXME: a frame that follows a keyframe generally doesn't need to be a keyframe
589        unless there's two consecutive stream boundaries. */
590     if (enc->curr_granule + 2*enc->frame_size>= end_granule48k && enc->streams->next) {
591       opeint_encoder_ctl(&enc->st, OPUS_SET_PREDICTION_DISABLED(1));
592       is_keyframe = 1;
593     }
594     /* Handle the last packet by making sure not to encode too much padding. */
595     if (enc->curr_granule+enc->frame_size >= end_granule48k && enc->draining && enc->frame_size_request > OPUS_FRAMESIZE_20_MS) {
596       int min_samples;
597       int frame_size_request = OPUS_FRAMESIZE_20_MS;
598       /* Minimum frame size required for the current frame to still meet the e_o_s condition. */
599       min_samples = end_granule48k - enc->curr_granule;
600       while (compute_frame_samples(frame_size_request) < min_samples) frame_size_request++;
601       assert(frame_size_request <= enc->frame_size_request);
602       ope_encoder_ctl(enc, OPUS_SET_EXPERT_FRAME_DURATION(frame_size_request));
603     }
604     packet = oggp_get_packet_buffer(enc->oggp, max_packet_size);
605     nbBytes = opeint_encode_float(&enc->st, &enc->buffer[enc->channels*enc->buffer_start],
606         enc->buffer_end-enc->buffer_start, packet, max_packet_size);
607     if (nbBytes < 0) {
608       /* Anything better we can do here? */
609       enc->unrecoverable = OPE_INTERNAL_ERROR;
610       return;
611     }
612     opeint_encoder_ctl(&enc->st, OPUS_SET_PREDICTION_DISABLED(pred));
613     assert(nbBytes > 0);
614     enc->curr_granule += enc->frame_size;
615     do {
616       int ret;
617       opus_int64 granulepos;
618       granulepos=enc->curr_granule-enc->streams->granule_offset;
619       e_o_s=enc->curr_granule >= end_granule48k;
620       cont = 0;
621       if (e_o_s) granulepos=end_granule48k-enc->streams->granule_offset;
622       if (packet_copy != NULL) {
623         packet = oggp_get_packet_buffer(enc->oggp, max_packet_size);
624         memcpy(packet, packet_copy, nbBytes);
625       }
626       if (enc->packet_callback) enc->packet_callback(enc->packet_callback_data, packet, nbBytes, 0);
627       if ((e_o_s || is_keyframe) && packet_copy == NULL) {
628         packet_copy = malloc(nbBytes);
629         if (packet_copy == NULL) {
630           /* Can't recover from allocation failing here. */
631           enc->unrecoverable = OPE_ALLOC_FAIL;
632           return;
633         }
634         memcpy(packet_copy, packet, nbBytes);
635       }
636       oggp_commit_packet(enc->oggp, nbBytes, granulepos, e_o_s);
637       if (e_o_s) ret = oe_flush_page(enc);
638       else if (!enc->pull_api) ret = output_pages(enc);
639       else ret = 0;
640       if (ret) {
641         enc->unrecoverable = OPE_WRITE_FAIL;
642         if (packet_copy) free(packet_copy);
643         return;
644       }
645       if (e_o_s) {
646         EncStream *tmp;
647         tmp = enc->streams->next;
648         if (enc->streams->close_at_end && !enc->pull_api) {
649           ret = enc->callbacks.close(enc->streams->user_data);
650           if (ret) {
651             enc->unrecoverable = OPE_CLOSE_FAIL;
652             free(packet_copy);
653             return;
654           }
655         }
656         stream_destroy(enc->streams);
657         enc->streams = tmp;
658         if (!tmp) enc->last_stream = NULL;
659         if (enc->last_stream == NULL) {
660           free(packet_copy);
661           return;
662         }
663         /* We're done with this stream, start the next one. */
664         enc->header.preskip = end_granule48k + enc->frame_size - enc->curr_granule;
665         enc->streams->granule_offset = enc->curr_granule - enc->frame_size;
666         if (enc->chaining_keyframe) {
667           enc->header.preskip += enc->frame_size;
668           enc->streams->granule_offset -= enc->frame_size;
669         }
670         init_stream(enc);
671         if (enc->chaining_keyframe) {
672           unsigned char *p;
673           opus_int64 granulepos2=enc->curr_granule - enc->streams->granule_offset - enc->frame_size;
674           p = oggp_get_packet_buffer(enc->oggp, enc->chaining_keyframe_length);
675           memcpy(p, enc->chaining_keyframe, enc->chaining_keyframe_length);
676           if (enc->packet_callback) enc->packet_callback(enc->packet_callback_data, enc->chaining_keyframe, enc->chaining_keyframe_length, 0);
677           oggp_commit_packet(enc->oggp, enc->chaining_keyframe_length, granulepos2, 0);
678         }
679         end_granule48k = (enc->streams->end_granule*48000 + enc->rate - 1)/enc->rate + enc->global_granule_offset;
680         cont = 1;
681       }
682     } while (cont);
683     if (enc->chaining_keyframe) free(enc->chaining_keyframe);
684     if (is_keyframe) {
685       enc->chaining_keyframe_length = nbBytes;
686       enc->chaining_keyframe = packet_copy;
687       packet_copy = NULL;
688     } else {
689       enc->chaining_keyframe = NULL;
690       enc->chaining_keyframe_length = -1;
691     }
692     if (packet_copy) free(packet_copy);
693     enc->buffer_start += enc->frame_size;
694   }
695   /* If we've reached the end of the buffer, move everything back to the front. */
696   if (enc->buffer_end == BUFFER_SAMPLES) {
697     shift_buffer(enc);
698   }
699   /* This function must never leave the buffer full. */
700   assert(enc->buffer_end < BUFFER_SAMPLES);
701 }
702 
703 /* Add/encode any number of float samples to the file. */
ope_encoder_write_float(OggOpusEnc * enc,const float * pcm,int samples_per_channel)704 int ope_encoder_write_float(OggOpusEnc *enc, const float *pcm, int samples_per_channel) {
705   int channels = enc->channels;
706   if (enc->unrecoverable) return enc->unrecoverable;
707   enc->last_stream->header_is_frozen = 1;
708   if (!enc->streams->stream_is_init) init_stream(enc);
709   if (samples_per_channel < 0) return OPE_BAD_ARG;
710   enc->write_granule += samples_per_channel;
711   enc->last_stream->end_granule = enc->write_granule;
712   if (enc->lpc_buffer) {
713     int i;
714     if (samples_per_channel < LPC_INPUT) {
715       for (i=0;i<(LPC_INPUT-samples_per_channel)*channels;i++) enc->lpc_buffer[i] = enc->lpc_buffer[samples_per_channel*channels + i];
716       for (i=0;i<samples_per_channel*channels;i++) enc->lpc_buffer[(LPC_INPUT-samples_per_channel)*channels + i] = pcm[i];
717     } else {
718       for (i=0;i<LPC_INPUT*channels;i++) enc->lpc_buffer[i] = pcm[(samples_per_channel-LPC_INPUT)*channels + i];
719     }
720   }
721   do {
722     int i;
723     spx_uint32_t in_samples, out_samples;
724     out_samples = BUFFER_SAMPLES-enc->buffer_end;
725     if (enc->re != NULL) {
726       in_samples = samples_per_channel;
727       speex_resampler_process_interleaved_float(enc->re, pcm, &in_samples, &enc->buffer[channels*enc->buffer_end], &out_samples);
728     } else {
729       int curr;
730       curr = MIN((spx_uint32_t)samples_per_channel, out_samples);
731       for (i=0;i<channels*curr;i++) {
732       enc->buffer[channels*enc->buffer_end+i] = pcm[i];
733       }
734       in_samples = out_samples = curr;
735     }
736     enc->buffer_end += out_samples;
737     pcm += in_samples*channels;
738     samples_per_channel -= in_samples;
739     encode_buffer(enc);
740     if (enc->unrecoverable) return enc->unrecoverable;
741   } while (samples_per_channel > 0);
742   return OPE_OK;
743 }
744 
745 #define CONVERT_BUFFER 4096
746 
747 /* Add/encode any number of int16 samples to the file. */
ope_encoder_write(OggOpusEnc * enc,const opus_int16 * pcm,int samples_per_channel)748 int ope_encoder_write(OggOpusEnc *enc, const opus_int16 *pcm, int samples_per_channel) {
749   int channels = enc->channels;
750   if (enc->unrecoverable) return enc->unrecoverable;
751   enc->last_stream->header_is_frozen = 1;
752   if (!enc->streams->stream_is_init) init_stream(enc);
753   if (samples_per_channel < 0) return OPE_BAD_ARG;
754   enc->write_granule += samples_per_channel;
755   enc->last_stream->end_granule = enc->write_granule;
756   if (enc->lpc_buffer) {
757     int i;
758     if (samples_per_channel < LPC_INPUT) {
759       for (i=0;i<(LPC_INPUT-samples_per_channel)*channels;i++) enc->lpc_buffer[i] = enc->lpc_buffer[samples_per_channel*channels + i];
760       for (i=0;i<samples_per_channel*channels;i++) enc->lpc_buffer[(LPC_INPUT-samples_per_channel)*channels + i] = (1.f/32768)*pcm[i];
761     } else {
762       for (i=0;i<LPC_INPUT*channels;i++) enc->lpc_buffer[i] = (1.f/32768)*pcm[(samples_per_channel-LPC_INPUT)*channels + i];
763     }
764   }
765   do {
766     int i;
767     spx_uint32_t in_samples, out_samples;
768     out_samples = BUFFER_SAMPLES-enc->buffer_end;
769     if (enc->re != NULL) {
770       float buf[CONVERT_BUFFER];
771       in_samples = MIN(CONVERT_BUFFER/channels, samples_per_channel);
772       for (i=0;i<channels*(int)in_samples;i++) {
773         buf[i] = (1.f/32768)*pcm[i];
774       }
775       speex_resampler_process_interleaved_float(enc->re, buf, &in_samples, &enc->buffer[channels*enc->buffer_end], &out_samples);
776     } else {
777       int curr;
778       curr = MIN((spx_uint32_t)samples_per_channel, out_samples);
779       for (i=0;i<channels*curr;i++) {
780         enc->buffer[channels*enc->buffer_end+i] = (1.f/32768)*pcm[i];
781       }
782       in_samples = out_samples = curr;
783     }
784     enc->buffer_end += out_samples;
785     pcm += in_samples*channels;
786     samples_per_channel -= in_samples;
787     encode_buffer(enc);
788     if (enc->unrecoverable) return enc->unrecoverable;
789   } while (samples_per_channel > 0);
790   return OPE_OK;
791 }
792 
793 /* Get the next page from the stream. Returns 1 if there is a page available, 0 if not. */
ope_encoder_get_page(OggOpusEnc * enc,unsigned char ** page,opus_int32 * len,int flush)794 int ope_encoder_get_page(OggOpusEnc *enc, unsigned char **page, opus_int32 *len, int flush) {
795   if (enc->unrecoverable) return enc->unrecoverable;
796   if (!enc->pull_api) return 0;
797   else {
798     if (flush) oggp_flush_page(enc->oggp);
799     return oggp_get_next_page(enc->oggp, page, len);
800   }
801 }
802 
803 static void extend_signal(float *x, int before, int after, int channels);
804 
ope_encoder_drain(OggOpusEnc * enc)805 int ope_encoder_drain(OggOpusEnc *enc) {
806   int pad_samples;
807   int resampler_drain = 0;
808   if (enc->unrecoverable) return enc->unrecoverable;
809   /* Check if it's already been drained. */
810   if (enc->streams == NULL) return OPE_TOO_LATE;
811   if (enc->re) resampler_drain = speex_resampler_get_output_latency(enc->re);
812   pad_samples = MAX(LPC_PADDING, enc->global_granule_offset + enc->frame_size + resampler_drain + 1);
813   if (!enc->streams->stream_is_init) init_stream(enc);
814   shift_buffer(enc);
815   assert(enc->buffer_end + pad_samples <= BUFFER_SAMPLES);
816   memset(&enc->buffer[enc->channels*enc->buffer_end], 0, pad_samples*enc->channels*sizeof(enc->buffer[0]));
817   if (enc->re) {
818     spx_uint32_t in_samples, out_samples;
819     extend_signal(&enc->lpc_buffer[LPC_INPUT*enc->channels], LPC_INPUT, LPC_PADDING, enc->channels);
820     do {
821       in_samples = LPC_PADDING;
822       out_samples = pad_samples;
823       speex_resampler_process_interleaved_float(enc->re, &enc->lpc_buffer[LPC_INPUT*enc->channels], &in_samples, &enc->buffer[enc->channels*enc->buffer_end], &out_samples);
824       enc->buffer_end += out_samples;
825       pad_samples -= out_samples;
826       /* If we don't have enough padding, zero all zeros and repeat. */
827       memset(&enc->lpc_buffer[LPC_INPUT*enc->channels], 0, LPC_PADDING*enc->channels*sizeof(enc->lpc_buffer[0]));
828     } while (pad_samples > 0);
829   } else {
830     extend_signal(&enc->buffer[enc->channels*enc->buffer_end], enc->buffer_end, LPC_PADDING, enc->channels);
831     enc->buffer_end += pad_samples;
832   }
833   enc->decision_delay = 0;
834   enc->draining = 1;
835   assert(enc->buffer_end <= BUFFER_SAMPLES);
836   encode_buffer(enc);
837   if (enc->unrecoverable) return enc->unrecoverable;
838   /* Draining should have called all the streams to complete. */
839   assert(enc->streams == NULL);
840   return OPE_OK;
841 }
842 
ope_encoder_destroy(OggOpusEnc * enc)843 void ope_encoder_destroy(OggOpusEnc *enc) {
844   EncStream *stream;
845   stream = enc->streams;
846   while (stream != NULL) {
847     EncStream *tmp = stream;
848     stream = stream->next;
849     /* Ignore any error on close. */
850     if (tmp->close_at_end && !enc->pull_api) enc->callbacks.close(tmp->user_data);
851     stream_destroy(tmp);
852   }
853   if (enc->chaining_keyframe) free(enc->chaining_keyframe);
854   free(enc->buffer);
855   if (enc->oggp) oggp_destroy(enc->oggp);
856   opeint_encoder_cleanup(&enc->st);
857   if (enc->re) speex_resampler_destroy(enc->re);
858   if (enc->lpc_buffer) free(enc->lpc_buffer);
859   free(enc);
860 }
861 
862 /* Ends the stream and create a new stream within the same file. */
ope_encoder_chain_current(OggOpusEnc * enc,OggOpusComments * comments)863 int ope_encoder_chain_current(OggOpusEnc *enc, OggOpusComments *comments) {
864   enc->last_stream->close_at_end = 0;
865   return ope_encoder_continue_new_callbacks(enc, enc->last_stream->user_data, comments);
866 }
867 
868 /* Ends the stream and create a new file. */
ope_encoder_continue_new_file(OggOpusEnc * enc,const char * path,OggOpusComments * comments)869 int ope_encoder_continue_new_file(OggOpusEnc *enc, const char *path, OggOpusComments *comments) {
870   int ret;
871   struct StdioObject *obj;
872   if (!(obj = malloc(sizeof(*obj)))) return OPE_ALLOC_FAIL;
873   obj->file = opeint_fopen(path, "wb");
874   if (!obj->file) {
875     free(obj);
876     /* By trying to open the file first, we can recover if we can't open it. */
877     return OPE_CANNOT_OPEN;
878   }
879   ret = ope_encoder_continue_new_callbacks(enc, obj, comments);
880   if (ret == OPE_OK) return ret;
881   fclose(obj->file);
882   free(obj);
883   return ret;
884 }
885 
886 /* Ends the stream and create a new file (callback-based). */
ope_encoder_continue_new_callbacks(OggOpusEnc * enc,void * user_data,OggOpusComments * comments)887 int ope_encoder_continue_new_callbacks(OggOpusEnc *enc, void *user_data, OggOpusComments *comments) {
888   EncStream *new_stream;
889   if (enc->unrecoverable) return enc->unrecoverable;
890   assert(enc->streams);
891   assert(enc->last_stream);
892   new_stream = stream_create(comments);
893   if (!new_stream) return OPE_ALLOC_FAIL;
894   new_stream->user_data = user_data;
895   new_stream->end_granule = enc->write_granule;
896   enc->last_stream->next = new_stream;
897   enc->last_stream = new_stream;
898   return OPE_OK;
899 }
900 
ope_encoder_flush_header(OggOpusEnc * enc)901 int ope_encoder_flush_header(OggOpusEnc *enc) {
902   if (enc->unrecoverable) return enc->unrecoverable;
903   if (enc->last_stream->header_is_frozen) return OPE_TOO_LATE;
904   if (enc->last_stream->stream_is_init) return OPE_TOO_LATE;
905   else init_stream(enc);
906   return OPE_OK;
907 }
908 
909 /* Goes straight to the libopus ctl() functions. */
ope_encoder_ctl(OggOpusEnc * enc,int request,...)910 int ope_encoder_ctl(OggOpusEnc *enc, int request, ...) {
911   int ret;
912   int translate;
913   va_list ap;
914   if (enc->unrecoverable) return enc->unrecoverable;
915   va_start(ap, request);
916   ret = OPE_OK;
917   switch (request) {
918     case OPUS_SET_APPLICATION_REQUEST:
919     case OPUS_SET_BITRATE_REQUEST:
920     case OPUS_SET_MAX_BANDWIDTH_REQUEST:
921     case OPUS_SET_VBR_REQUEST:
922     case OPUS_SET_BANDWIDTH_REQUEST:
923     case OPUS_SET_COMPLEXITY_REQUEST:
924     case OPUS_SET_INBAND_FEC_REQUEST:
925     case OPUS_SET_PACKET_LOSS_PERC_REQUEST:
926     case OPUS_SET_DTX_REQUEST:
927     case OPUS_SET_VBR_CONSTRAINT_REQUEST:
928     case OPUS_SET_FORCE_CHANNELS_REQUEST:
929     case OPUS_SET_SIGNAL_REQUEST:
930     case OPUS_SET_LSB_DEPTH_REQUEST:
931     case OPUS_SET_PREDICTION_DISABLED_REQUEST:
932 #ifdef OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST
933     case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
934 #endif
935     {
936       opus_int32 value = va_arg(ap, opus_int32);
937       ret = opeint_encoder_ctl2(&enc->st, request, value);
938     }
939     break;
940     case OPUS_GET_LOOKAHEAD_REQUEST:
941     {
942       opus_int32 *value = va_arg(ap, opus_int32*);
943       ret = opeint_encoder_ctl(&enc->st, OPUS_GET_LOOKAHEAD(value));
944     }
945     break;
946     case OPUS_SET_EXPERT_FRAME_DURATION_REQUEST:
947     {
948       opus_int32 value = va_arg(ap, opus_int32);
949       int max_supported = OPUS_FRAMESIZE_60_MS;
950 #ifdef OPUS_FRAMESIZE_120_MS
951       max_supported = OPUS_FRAMESIZE_120_MS;
952 #endif
953       if (value < OPUS_FRAMESIZE_2_5_MS || value > max_supported) {
954         ret = OPUS_UNIMPLEMENTED;
955         break;
956       }
957       ret = opeint_encoder_ctl(&enc->st, OPUS_SET_EXPERT_FRAME_DURATION(value));
958       if (ret == OPUS_OK) {
959         enc->frame_size = compute_frame_samples(value);
960         enc->frame_size_request = value;
961       }
962     }
963     break;
964     case OPUS_GET_APPLICATION_REQUEST:
965     case OPUS_GET_BITRATE_REQUEST:
966     case OPUS_GET_MAX_BANDWIDTH_REQUEST:
967     case OPUS_GET_VBR_REQUEST:
968     case OPUS_GET_BANDWIDTH_REQUEST:
969     case OPUS_GET_COMPLEXITY_REQUEST:
970     case OPUS_GET_INBAND_FEC_REQUEST:
971     case OPUS_GET_PACKET_LOSS_PERC_REQUEST:
972     case OPUS_GET_DTX_REQUEST:
973     case OPUS_GET_VBR_CONSTRAINT_REQUEST:
974     case OPUS_GET_FORCE_CHANNELS_REQUEST:
975     case OPUS_GET_SIGNAL_REQUEST:
976     case OPUS_GET_LSB_DEPTH_REQUEST:
977     case OPUS_GET_PREDICTION_DISABLED_REQUEST:
978 #ifdef OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST
979     case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
980 #endif
981     {
982       opus_int32 *value = va_arg(ap, opus_int32*);
983       ret = opeint_encoder_ctl2(&enc->st, request, value);
984     }
985     break;
986     case OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST:
987     {
988       opus_int32 stream_id;
989       OpusEncoder **value;
990       stream_id = va_arg(ap, opus_int32);
991       value = va_arg(ap, OpusEncoder**);
992       opeint_encoder_ctl(&enc->st, OPUS_MULTISTREAM_GET_ENCODER_STATE(stream_id, value));
993     }
994     break;
995 
996     /* ****************** libopusenc-specific requests. ********************** */
997     case OPE_SET_DECISION_DELAY_REQUEST:
998     {
999       opus_int32 value = va_arg(ap, opus_int32);
1000       if (value < 0) {
1001         ret = OPE_BAD_ARG;
1002         break;
1003       }
1004       value = MIN(value, MAX_LOOKAHEAD);
1005       enc->decision_delay = value;
1006     }
1007     break;
1008     case OPE_GET_DECISION_DELAY_REQUEST:
1009     {
1010       opus_int32 *value = va_arg(ap, opus_int32*);
1011       *value = enc->decision_delay;
1012     }
1013     break;
1014     case OPE_SET_MUXING_DELAY_REQUEST:
1015     {
1016       opus_int32 value = va_arg(ap, opus_int32);
1017       if (value < 0) {
1018         ret = OPE_BAD_ARG;
1019         break;
1020       }
1021       enc->max_ogg_delay = value;
1022       if (enc->oggp) oggp_set_muxing_delay(enc->oggp, enc->max_ogg_delay);
1023     }
1024     break;
1025     case OPE_GET_MUXING_DELAY_REQUEST:
1026     {
1027       opus_int32 *value = va_arg(ap, opus_int32*);
1028       *value = enc->max_ogg_delay;
1029     }
1030     break;
1031     case OPE_SET_COMMENT_PADDING_REQUEST:
1032     {
1033       opus_int32 value = va_arg(ap, opus_int32);
1034       if (value < 0) {
1035         ret = OPE_BAD_ARG;
1036         break;
1037       }
1038       enc->comment_padding = value;
1039       ret = OPE_OK;
1040     }
1041     break;
1042     case OPE_GET_COMMENT_PADDING_REQUEST:
1043     {
1044       opus_int32 *value = va_arg(ap, opus_int32*);
1045       *value = enc->comment_padding;
1046     }
1047     break;
1048     case OPE_SET_SERIALNO_REQUEST:
1049     {
1050       opus_int32 value = va_arg(ap, opus_int32);
1051       if (!enc->last_stream || enc->last_stream->header_is_frozen) {
1052         ret = OPE_TOO_LATE;
1053         break;
1054       }
1055       enc->last_stream->serialno = value;
1056       enc->last_stream->serialno_is_set = 1;
1057       ret = OPE_OK;
1058     }
1059     break;
1060     case OPE_GET_SERIALNO_REQUEST:
1061     {
1062       opus_int32 *value = va_arg(ap, opus_int32*);
1063       *value = enc->last_stream->serialno;
1064     }
1065     break;
1066     case OPE_SET_PACKET_CALLBACK_REQUEST:
1067     {
1068       ope_packet_func value = va_arg(ap, ope_packet_func);
1069       void *data = va_arg(ap, void *);
1070       enc->packet_callback = value;
1071       enc->packet_callback_data = data;
1072       ret = OPE_OK;
1073     }
1074     break;
1075     case OPE_SET_HEADER_GAIN_REQUEST:
1076     {
1077       opus_int32 value = va_arg(ap, opus_int32);
1078       if (!enc->last_stream || enc->last_stream->header_is_frozen) {
1079         ret = OPE_TOO_LATE;
1080         break;
1081       }
1082       enc->header.gain = value;
1083       ret = OPE_OK;
1084     }
1085     break;
1086     case OPE_GET_HEADER_GAIN_REQUEST:
1087     {
1088       opus_int32 *value = va_arg(ap, opus_int32*);
1089       *value = enc->header.gain;
1090     }
1091     break;
1092     case OPE_GET_NB_STREAMS_REQUEST:
1093     {
1094       opus_int32 *value = va_arg(ap, opus_int32*);
1095       *value = enc->header.nb_streams;
1096     }
1097     break;
1098     case OPE_GET_NB_COUPLED_STREAMS_REQUEST:
1099     {
1100       opus_int32 *value = va_arg(ap, opus_int32*);
1101       *value = enc->header.nb_coupled;
1102     }
1103     break;
1104     default:
1105       ret = OPUS_UNIMPLEMENTED;
1106   }
1107   va_end(ap);
1108   translate = ret != 0 && (request < 14000 || (ret < 0 && ret >= -10));
1109   if (translate) {
1110     if (ret == OPUS_BAD_ARG) ret = OPE_BAD_ARG;
1111     else if (ret == OPUS_INTERNAL_ERROR) ret = OPE_INTERNAL_ERROR;
1112     else if (ret == OPUS_UNIMPLEMENTED) ret = OPE_UNIMPLEMENTED;
1113     else if (ret == OPUS_ALLOC_FAIL) ret = OPE_ALLOC_FAIL;
1114     else ret = OPE_INTERNAL_ERROR;
1115   }
1116   assert(ret == 0 || ret < -10);
1117   return ret;
1118 }
1119 
ope_strerror(int error)1120 const char *ope_strerror(int error) {
1121   static const char * const ope_error_strings[] = {
1122     "cannot open file",
1123     "call cannot be made at this point",
1124     "invalid picture file",
1125     "invalid icon file (pictures of type 1 MUST be 32x32 PNGs)",
1126     "write failed",
1127     "close failed"
1128   };
1129   if (error == 0) return "success";
1130   else if (error >= -10) return "unknown error";
1131   else if (error > -30) return opus_strerror(error+10);
1132   else if (error >= OPE_CLOSE_FAIL) return ope_error_strings[-error-30];
1133   else return "unknown error";
1134 }
1135 
ope_get_version_string(void)1136 const char *ope_get_version_string(void)
1137 {
1138   return "libopusenc " PACKAGE_VERSION;
1139 }
1140 
ope_get_abi_version(void)1141 int ope_get_abi_version(void) {
1142   return OPE_ABI_VERSION;
1143 }
1144 
1145 static void vorbis_lpc_from_data(float *data, float *lpci, int n, int stride);
1146 
extend_signal(float * x,int before,int after,int channels)1147 static void extend_signal(float *x, int before, int after, int channels) {
1148   int c;
1149   int i;
1150   float window[LPC_PADDING];
1151   if (after==0) return;
1152   before = MIN(before, LPC_INPUT);
1153   if (before < 4*LPC_ORDER) {
1154     int i;
1155     for (i=0;i<after*channels;i++) x[i] = 0;
1156     return;
1157   }
1158   {
1159     /* Generate Window using a resonating IIR aka Goertzel's algorithm. */
1160     float m0=1, m1=.5*LPC_GOERTZEL_CONST;
1161     float a1 = LPC_GOERTZEL_CONST;
1162     window[0] = 1;
1163     for (i=1;i<LPC_PADDING;i++) {
1164       window[i] = a1*m0 - m1;
1165       m1 = m0;
1166       m0 = window[i];
1167     }
1168     for (i=0;i<LPC_PADDING;i++) window[i] = .5+.5*window[i];
1169   }
1170   for (c=0;c<channels;c++) {
1171     float lpc[LPC_ORDER];
1172     vorbis_lpc_from_data(x-channels*before+c, lpc, before, channels);
1173     for (i=0;i<after;i++) {
1174       float sum;
1175       int j;
1176       sum = 0;
1177       for (j=0;j<LPC_ORDER;j++) sum -= x[(i-j-1)*channels + c]*lpc[j];
1178       x[i*channels + c] = sum;
1179     }
1180     for (i=0;i<after;i++) x[i*channels + c] *= window[i];
1181   }
1182 }
1183 
1184 /* Some of these routines (autocorrelator, LPC coefficient estimator)
1185    are derived from code written by Jutta Degener and Carsten Bormann;
1186    thus we include their copyright below.  The entirety of this file
1187    is freely redistributable on the condition that both of these
1188    copyright notices are preserved without modification.  */
1189 
1190 /* Preserved Copyright: *********************************************/
1191 
1192 /* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
1193 Technische Universita"t Berlin
1194 
1195 Any use of this software is permitted provided that this notice is not
1196 removed and that neither the authors nor the Technische Universita"t
1197 Berlin are deemed to have made any representations as to the
1198 suitability of this software for any purpose nor are held responsible
1199 for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
1200 THIS SOFTWARE.
1201 
1202 As a matter of courtesy, the authors request to be informed about uses
1203 this software has found, about bugs in this software, and about any
1204 improvements that may be of general interest.
1205 
1206 Berlin, 28.11.1994
1207 Jutta Degener
1208 Carsten Bormann
1209 
1210 *********************************************************************/
1211 
vorbis_lpc_from_data(float * data,float * lpci,int n,int stride)1212 static void vorbis_lpc_from_data(float *data, float *lpci, int n, int stride) {
1213   double aut[LPC_ORDER+1];
1214   double lpc[LPC_ORDER];
1215   double error;
1216   double epsilon;
1217   int i,j;
1218 
1219   /* FIXME: Apply a window to the input. */
1220   /* autocorrelation, p+1 lag coefficients */
1221   j=LPC_ORDER+1;
1222   while(j--){
1223     double d=0; /* double needed for accumulator depth */
1224     for(i=j;i<n;i++)d+=(double)data[i*stride]*data[(i-j)*stride];
1225     aut[j]=d;
1226   }
1227 
1228   /* Apply lag windowing (better than bandwidth expansion) */
1229   if (LPC_ORDER <= 64) {
1230     for (i=1;i<=LPC_ORDER;i++) {
1231       /* Approximate this gaussian for low enough order. */
1232       /* aut[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
1233       aut[i] -= aut[i]*(0.008f*0.008f)*i*i;
1234     }
1235   }
1236   /* Generate lpc coefficients from autocorr values */
1237 
1238   /* set our noise floor to about -100dB */
1239   error=aut[0] * (1. + 1e-7);
1240   epsilon=1e-6*aut[0]+1e-7;
1241 
1242   for(i=0;i<LPC_ORDER;i++){
1243     double r= -aut[i+1];
1244 
1245     if(error<epsilon){
1246       memset(lpc+i,0,(LPC_ORDER-i)*sizeof(*lpc));
1247       goto done;
1248     }
1249 
1250     /* Sum up this iteration's reflection coefficient; note that in
1251        Vorbis we don't save it.  If anyone wants to recycle this code
1252        and needs reflection coefficients, save the results of 'r' from
1253        each iteration. */
1254 
1255     for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
1256     r/=error;
1257 
1258     /* Update LPC coefficients and total error */
1259 
1260     lpc[i]=r;
1261     for(j=0;j<i/2;j++){
1262       double tmp=lpc[j];
1263 
1264       lpc[j]+=r*lpc[i-1-j];
1265       lpc[i-1-j]+=r*tmp;
1266     }
1267     if(i&1)lpc[j]+=lpc[j]*r;
1268 
1269     error*=1.-r*r;
1270 
1271   }
1272 
1273  done:
1274 
1275   /* slightly damp the filter */
1276   {
1277     double g = .999;
1278     double damp = g;
1279     for(j=0;j<LPC_ORDER;j++){
1280       lpc[j]*=damp;
1281       damp*=g;
1282     }
1283   }
1284 
1285   for(j=0;j<LPC_ORDER;j++)lpci[j]=(float)lpc[j];
1286 }
1287 
1288