Some encoding code
[libopusenc.git] / src / opusenc.c
1 /* Copyright (C)2002-2017 Jean-Marc Valin
2    Copyright (C)2007-2013 Xiph.Org Foundation
3    Copyright (C)2008-2013 Gregory Maxwell
4    File: opusenc.c
5
6    Redistribution and use in source and binary forms, with or without
7    modification, are permitted provided that the following conditions
8    are met:
9
10    - Redistributions of source code must retain the above copyright
11    notice, this list of conditions and the following disclaimer.
12
13    - Redistributions in binary form must reproduce the above copyright
14    notice, this list of conditions and the following disclaimer in the
15    documentation and/or other materials provided with the distribution.
16
17    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
21    OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #ifdef HAVE_CONFIG_H
31 #include "config.h"
32 #endif
33
34 #include <time.h>
35 #include <unistd.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <assert.h>
39 #include <opus_multistream.h>
40 #include "opusenc.h"
41 #include "opus_header.h"
42
43 #define LPC_PADDING 120
44
45 /* Allow up to 2 seconds for delayed decision. */
46 #define MAX_LOOKAHEAD 96000
47 /* We can't have a circular buffer (because of delayed decision), so let's not copy too often. */
48 #define BUFFER_EXTRA 24000
49
50 #define BUFFER_SAMPLES (MAX_LOOKAHEAD + BUFFER_EXTRA)
51
52 #define MIN(a,b) ((a) < (b) ? (a) : (b))
53 #define MAX(a,b) ((a) > (b) ? (a) : (b))
54
55
56 static int oe_write_page(ogg_page *page, OpusEncCallbacks *cb, void *user_data)
57 {
58    int err;
59    err = cb->write(user_data, page->header, page->header_len);
60    if (err) return -1;
61    err = cb->write(user_data, page->body, page->body_len);
62    if (err) return -1;
63    return page->header_len+page->body_len;
64 }
65
66 struct StdioObject {
67   FILE *file;
68 };
69
70 struct OggOpusEnc {
71   OpusMSEncoder *st;
72   int channels;
73   float *buffer;
74   int buffer_start;
75   int buffer_end;
76   OpusEncCallbacks callbacks;
77   void *user_data;
78   OpusHeader header;
79   char *comment;
80   int comment_length;
81   int os_allocated;
82   ogg_stream_state os;
83   int stream_is_init;
84 };
85
86 static int oe_flush_page(OggOpusEnc *enc) {
87   ogg_page og;
88   int ret;
89   int written = 0;
90   while ( (ret = ogg_stream_flush(&enc->os, &og)) ) {
91     if (!ret) break;
92     ret = oe_write_page(&og, &enc->callbacks, enc->user_data);
93     if (ret == -1) {
94       return -1;
95     }
96     written += ret;
97   }
98   return written;
99 }
100
101 int stdio_write(void *user_data, const unsigned char *ptr, int len) {
102   struct StdioObject *obj = (struct StdioObject*)user_data;
103   return fwrite(ptr, 1, len, obj->file) != (size_t)len;
104 }
105
106 int stdio_close(void *user_data) {
107   struct StdioObject *obj = (struct StdioObject*)user_data;
108   int ret = fclose(obj->file);
109   free(obj);
110   return ret;
111 }
112
113 static const OpusEncCallbacks stdio_callbacks = {
114   stdio_write,
115   stdio_close
116 };
117
118 /* Create a new OggOpus file. */
119 OggOpusEnc *ope_create_file(const char *path, int rate, int channels, int family, int *error) {
120   OggOpusEnc *enc;
121   struct StdioObject *obj;
122   obj = malloc(sizeof(*obj));
123   enc = ope_create_callbacks(&stdio_callbacks, obj, rate, channels, family, error);
124   if (enc == NULL || (error && *error)) {
125     return NULL;
126   }
127   obj->file = fopen(path, "wb");
128   if (!obj->file) {
129     if (error) *error = OPE_CANNOT_OPEN;
130     /* FIXME: Destroy the encoder properly. */
131     free(obj);
132     return NULL;
133   }
134   return enc;
135 }
136
137 /* Create a new OggOpus file (callback-based). */
138 OggOpusEnc *ope_create_callbacks(const OpusEncCallbacks *callbacks, void *user_data,
139     int rate, int channels, int family, int *error) {
140   OpusMSEncoder *st=NULL;
141   OggOpusEnc *enc=NULL;
142   int ret;
143   if (family != 0 && family != 1 && family != 255) {
144     if (error) *error = OPE_UNIMPLEMENTED;
145     return NULL;
146   }
147   if (channels <= 0 || channels > 255) {
148     if (error) *error = OPE_BAD_ARG;
149     return NULL;
150   }
151   /* FIXME: Add resampling support. */
152   if (rate != 48000) {
153     if (error) *error = OPE_UNIMPLEMENTED;
154     return NULL;
155   }
156   if ( (enc = malloc(sizeof(*enc))) == NULL) goto fail;
157   enc->channels = channels;
158   enc->header.channels=channels;
159   enc->header.channel_mapping=family;
160   enc->header.input_sample_rate=rate;
161   enc->header.gain=0;
162   st=opus_multistream_surround_encoder_create(48000, channels, enc->header.channel_mapping,
163       &enc->header.nb_streams, &enc->header.nb_coupled,
164       enc->header.stream_map, OPUS_APPLICATION_AUDIO, &ret);
165   if (! (ret == OPUS_OK && st != NULL) ) {
166     goto fail;
167   }
168   enc->os_allocated = 0;
169   enc->stream_is_init = 0;
170   enc->comment = NULL;
171   comment_init(&enc->comment, &enc->comment_length, opus_get_version_string());
172   {
173     char encoder_string[1024];
174     snprintf(encoder_string, sizeof(encoder_string), "%s version %s", PACKAGE_NAME, PACKAGE_VERSION);
175     comment_add(&enc->comment, &enc->comment_length, "ENCODER", encoder_string);
176   }
177   if (enc->comment == NULL) goto fail;
178   if ( (enc->buffer = malloc(sizeof(*enc->buffer)*BUFFER_SAMPLES*channels)) == NULL) goto fail;
179   enc->st = st;
180   enc->callbacks = *callbacks;
181   enc->user_data = user_data;
182   return enc;
183 fail:
184   if (enc) {
185     free(enc);
186     if (enc->buffer) free(enc->buffer);
187   }
188   if (st) {
189     opus_multistream_encoder_destroy(st);
190   }
191   return NULL;
192 }
193
194 static void init_stream(OggOpusEnc *enc) {
195   time_t start_time;
196   int serialno;
197   assert(!enc->stream_is_init);
198   start_time = time(NULL);
199   srand(((getpid()&65535)<<15)^start_time);
200
201   serialno = rand();
202   if (ogg_stream_init(&enc->os, serialno) == -1) {
203     assert(0);
204     /* FIXME: How the hell do we handle that? */
205   }
206   /* FIXME: Compute preskip. */
207   enc->header.preskip = 0;
208   comment_pad(&enc->comment, &enc->comment_length, 512);
209
210   /*Write header*/
211   {
212     ogg_packet op;
213     /*The Identification Header is 19 bytes, plus a Channel Mapping Table for
214       mapping families other than 0. The Channel Mapping Table is 2 bytes +
215       1 byte per channel. Because the maximum number of channels is 255, the
216       maximum size of this header is 19 + 2 + 255 = 276 bytes.*/
217     unsigned char header_data[276];
218     int packet_size = opus_header_to_packet(&enc->header, header_data, sizeof(header_data));
219     op.packet=header_data;
220     op.bytes=packet_size;
221     op.b_o_s=1;
222     op.e_o_s=0;
223     op.granulepos=0;
224     op.packetno=0;
225     ogg_stream_packetin(&enc->os, &op);
226     oe_flush_page(enc);
227
228     op.packet = (unsigned char *)enc->comment;
229     op.bytes = enc->comment_length;
230     op.b_o_s = 0;
231     op.e_o_s = 0;
232     op.granulepos = 0;
233     op.packetno = 1;
234     ogg_stream_packetin(&enc->os, &op);
235     oe_flush_page(enc);
236   }
237   enc->stream_is_init = 1;
238 }
239
240 static void encode_buffer(OggOpusEnc *enc) {
241   while (enc->buffer_end-enc->buffer_start > enc->frame_size + enc->decision_delay) {
242     unsigned char packet[MAX_PACKET_SIZE];
243     opus_multistream_encode_float(enc->st, &enc->buffer[enc->channels*enc->buffer_start],
244         enc->buffer_end-enc->buffer_start, packet, MAX_PACKET_SIZE);
245     /* FIXME: Write the packet to the stream. */
246     enc->buffer_start += frame_size;
247   }
248   /* This function must never leave the buffer full. */
249   assert(enc->buffer_end < BUFFER_SAMPLES);
250 }
251
252 /* Add/encode any number of float samples to the file. */
253 int ope_write_float(OggOpusEnc *enc, float *pcm, int samples_per_channel) {
254   int channels = enc->channels;
255   /* FIXME: Add resampling support. */
256   do {
257     int i;
258     int curr;
259     int space_left = BUFFER_SAMPLES-enc->buffer_end;
260     curr = MIN(samples_per_channel, space_left);
261     for (i=0;i<channels*curr;i++) {
262       enc->buffer[channels*enc->buffer_end+i] = pcm[i];
263     }
264     enc->buffer_end += curr;
265     pcm += curr;
266     samples_per_channel -= curr;
267     encode_buffer(enc);
268   } while (samples_per_channel > 0);
269   return 0;
270 }
271
272 /* Add/encode any number of int16 samples to the file. */
273 int ope_write(OggOpusEnc *enc, opus_int16 *pcm, int samples_per_channel) {
274   int channels = enc->channels;
275   /* FIXME: Add resampling support. */
276   do {
277     int i;
278     int curr;
279     int space_left = BUFFER_SAMPLES-enc->buffer_end;
280     curr = MIN(samples_per_channel, space_left);
281     for (i=0;i<channels*curr;i++) {
282       enc->buffer[channels*enc->buffer_end+i] = (1.f/32768)*pcm[i];
283     }
284     enc->buffer_end += curr;
285     pcm += curr;
286     samples_per_channel -= curr;
287     encode_buffer(enc);
288   } while (samples_per_channel > 0);
289   return 0;
290 }
291
292 static void finalize_stream(OggOpusEnc *enc) {
293   if (!enc->stream_is_init) init_stream(enc);
294 }
295
296 /* Close/finalize the stream. */
297 int ope_close_and_free(OggOpusEnc *enc) {
298   finalize_stream(enc);
299   free(enc->buffer);
300   opus_multistream_encoder_destroy(enc->st);
301   if (enc->os_allocated) ogg_stream_clear(&enc->os);
302   return OPE_OK;
303 }
304
305 /* Ends the stream and create a new stream within the same file. */
306 int ope_chain_current(OggOpusEnc *enc) {
307   (void)enc;
308   return 0;
309 }
310
311 /* Ends the stream and create a new file. */
312 int ope_continue_new_file(OggOpusEnc *enc, const char *path) {
313   (void)enc;
314   (void)path;
315   return 0;
316 }
317
318 /* Ends the stream and create a new file (callback-based). */
319 int ope_continue_new_callbacks(OggOpusEnc *enc, void *user_data) {
320   (void)enc;
321   (void)user_data;
322   return 0;
323 }
324
325 /* Add a comment to the file (can only be called before encoding samples). */
326 int ope_add_comment(OggOpusEnc *enc, char *tag, char *val) {
327   if (comment_add(&enc->comment, &enc->comment_length, tag, val)) return OPE_INTERNAL_ERROR;
328   return OPE_OK;
329 }
330
331 /* Sets the Opus comment vendor string (optional, defaults to library info). */
332 int ope_set_vendor_string(OggOpusEnc *enc, char *vendor) {
333   (void)enc;
334   (void)vendor;
335   return OPE_UNIMPLEMENTED;
336 }
337
338 /* Goes straight to the libopus ctl() functions. */
339 int ope_encoder_ctl(OggOpusEnc *enc, int request, ...) {
340   (void)enc;
341   (void)request;
342   return 0;
343 }
344
345 /* ctl()-type call for the OggOpus layer. */
346 int ope_set_params(OggOpusEnc *enc, int request, ...) {
347   (void)enc;
348   (void)request;
349   return 0;
350 }