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