Convert audiod commands to lopsub.
[paraslash.git] / opusdec_filter.c
1 /*
2  * Copyright (c) 2002-2007 Jean-Marc Valin
3  * Copyright (c) 2008 CSIRO
4  * Copyright (c) 2007-2012 Xiph.Org Foundation
5  * Copyright (C) 2012 Andre Noll <maan@tuebingen.mpg.de>
6  *
7  * Licensed under the GPL v2. For licencing details see COPYING.
8  */
9
10 /** \file opusdec_filter.c The ogg/opus decoder. */
11
12 /* This file is based on opusdec.c, by Jean-Marc Valin, see below. */
13
14 /*
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions are met:
17  *
18  * - Redistributions of source code must retain the above copyright notice,
19  * this list of conditions and the following disclaimer.
20  *
21  * - Redistributions in binary form must reproduce the above copyright notice,
22  * this list of conditions and the following disclaimer in the documentation
23  * and/or other materials provided with the distribution.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
26  * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
27  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE
29  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  */
37
38
39 /* Silence gcc warning caused by including opus.h */
40 #if !defined(__STDC_VERSION__)
41 #define __STDC_VERSION__ 0
42 #endif
43
44 #include <regex.h>
45 #include <opus/opus.h>
46 #include <opus/opus_multistream.h>
47 #include <ogg/ogg.h>
48 #include <math.h>
49
50 #include "para.h"
51 #include "list.h"
52 #include "sched.h"
53 #include "ggo.h"
54 #include "buffer_tree.h"
55 #include "filter.h"
56 #include "error.h"
57 #include "string.h"
58 #include "opus_common.h"
59
60 /** 120ms at 48000 */
61 #define MAX_FRAME_SIZE (960*6)
62
63 struct opusdec_context {
64         OpusMSDecoder *st;
65         opus_int64 packet_count;
66         int total_links;
67         bool stream_init;
68         ogg_sync_state oy;
69         ogg_stream_state os;
70         ogg_page ogg_page;
71         bool eos;
72         int channels;
73         uint16_t preskip;
74         bool have_opus_stream;
75         bool have_more;
76         ogg_int32_t opus_serialno;
77 };
78
79 static int opusdec_execute(struct btr_node *btrn, const char *cmd,
80                 char **result)
81 {
82         struct filter_node *fn = btr_context(btrn);
83         struct opusdec_context *ctx = fn->private_data;
84
85         return decoder_execute(cmd, 48000, ctx->channels, result);
86 }
87
88 static void opusdec_open(struct filter_node *fn)
89 {
90         struct opusdec_context *ctx = para_calloc(sizeof(*ctx));
91
92         ogg_sync_init(&ctx->oy);
93         fn->private_data = ctx;
94 }
95
96 static void opusdec_close(struct filter_node *fn)
97 {
98         struct opusdec_context *ctx = fn->private_data;
99
100         if (ctx->st) {
101                 opus_multistream_decoder_destroy(ctx->st);
102                 if (ctx->stream_init)
103                         ogg_stream_clear(&ctx->os);
104                 ogg_sync_clear(&ctx->oy);
105         }
106         free(ctx);
107         fn->private_data = NULL;
108 }
109
110 /* Process an Opus header and setup the opus decoder based on it. */
111 static int opusdec_init(ogg_packet *op, struct opusdec_context *ctx)
112 {
113         int ret;
114         struct opus_header header;
115
116         ctx->st = NULL;
117         ret = opus_parse_header((char *)op->packet, op->bytes, &header);
118         if (ret < 0)
119                 return ret;
120         PARA_INFO_LOG("detected header v%d\n", header.version);
121         ctx->channels = header.channels;
122         ctx->preskip = header.preskip;
123         ctx->st = opus_multistream_decoder_create(48000, header.channels,
124                 header.nb_streams, header.nb_coupled, header.stream_map, &ret);
125         if (ret != OPUS_OK || !ctx->st) {
126                 PARA_ERROR_LOG("%s\n", opus_strerror(ret));
127                 return -E_CREATE_OPUS_DECODER;
128         }
129         if (header.gain != 0) {
130                 ret = opus_multistream_decoder_ctl(ctx->st,
131                         OPUS_SET_GAIN(header.gain));
132                 if (ret != OPUS_OK) {
133                         PARA_ERROR_LOG("%s\n", opus_strerror(ret));
134                         return -E_OPUS_SET_GAIN;
135                 }
136                 PARA_INFO_LOG("playback gain: %fdB\n", header.gain / 256.);
137         }
138         PARA_INFO_LOG("%d channel(s), 48KHz\n", ctx->channels);
139         return 1;
140 }
141
142 static void opusdec_add_output(short *pcm, int frames_available,
143                 struct btr_node *btrn, struct opusdec_context *ctx)
144 {
145         int num_frames, bytes;
146         uint16_t tmp_skip;
147
148         tmp_skip = PARA_MIN((int)ctx->preskip, frames_available);
149         ctx->preskip -= tmp_skip;
150         num_frames = frames_available - tmp_skip;
151         if (num_frames <= 0)
152                 return;
153         bytes = sizeof(short) * num_frames * ctx->channels;
154
155         if (tmp_skip > 0) {
156                 short *in = pcm + ctx->channels * tmp_skip;
157                 short *out = para_malloc(bytes);
158                 memcpy(out, in, bytes);
159                 free(pcm);
160                 pcm = out;
161         }
162         btr_add_output((char *)pcm, bytes, btrn);
163 }
164
165 /* returns > 1 if packet was decoded, 0 if it was ignored, negative on errors. */
166 static int decode_packet(struct opusdec_context *ctx, ogg_packet *op,
167                 struct btr_node *btrn)
168 {
169         int ret;
170         short *output;
171
172         /*
173          * OggOpus streams are identified by a magic string in the initial
174          * stream header.
175          */
176         if (op->b_o_s && op->bytes >= 8 && !memcmp(op->packet, "OpusHead", 8)) {
177                 if (!ctx->have_opus_stream) {
178                         ctx->opus_serialno = ctx->os.serialno;
179                         ctx->have_opus_stream = true;
180                         ctx->packet_count = 0;
181                         ctx->eos = false;
182                         ctx->total_links++;
183                 } else
184                         PARA_NOTICE_LOG("ignoring opus stream %llu\n",
185                                 (long long unsigned)ctx->os.serialno);
186         }
187         if (!ctx->have_opus_stream || ctx->os.serialno != ctx->opus_serialno)
188                 return 0;
189         /* If first packet in a logical stream, process the Opus header. */
190         if (ctx->packet_count == 0)
191                 return opusdec_init(op, ctx);
192         if (ctx->packet_count == 1)
193                 return 1;
194         /* don't care for anything except opus eos */
195         if (op->e_o_s && ctx->os.serialno == ctx->opus_serialno)
196                 ctx->eos = true;
197         output = para_malloc(sizeof(short) * MAX_FRAME_SIZE * ctx->channels);
198         ret = opus_multistream_decode(ctx->st, (unsigned char *)op->packet,
199                 op->bytes, output, MAX_FRAME_SIZE, 0);
200         if (ret < 0) {
201                 PARA_ERROR_LOG("%s\n", opus_strerror(ret));
202                 free(output);
203                 return -E_OPUS_DECODE;
204         }
205         opusdec_add_output(output, ret, btrn, ctx);
206         return 1;
207 }
208
209 #define OPUSDEC_MAX_OUTPUT_SIZE (1024 * 1024)
210
211 static int opusdec_post_select(__a_unused struct sched *s, void *context)
212 {
213         struct filter_node *fn = context;
214         struct opusdec_context *ctx = fn->private_data;
215         struct btr_node *btrn = fn->btrn;
216         int ret;
217         ogg_packet op;
218
219         ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
220         if (ret < 0) {
221                 if (ret != -E_BTR_EOF) /* fatal error */
222                         goto out;
223                 if (!ctx->have_more) /* EOF */
224                         goto out;
225         } else if (ret == 0 && !ctx->have_more) /* nothing to do */
226                 goto out;
227         if (btr_get_output_queue_size(btrn) > OPUSDEC_MAX_OUTPUT_SIZE)
228                 return 0;
229         for (;;) {
230                 int serial;
231                 if (ctx->stream_init) {
232                         ret = ogg_stream_packetout(&ctx->os, &op);
233                         if (ret == 1)
234                                 break;
235                 }
236                 while (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1) {
237                         char *btr_buf, *data;
238                         size_t nbytes = btr_next_buffer(btrn, &btr_buf);
239                         nbytes = PARA_MIN(nbytes, (size_t)24 * 1024);
240                         //PARA_CRIT_LOG("nbytes: %d\n", nbytes);
241                         ctx->have_more = false;
242                         if (nbytes == 0)
243                                 return 0;
244                         data = ogg_sync_buffer(&ctx->oy, nbytes);
245                         memcpy(data, btr_buf, nbytes);
246                         btr_consume(btrn, nbytes);
247                         ogg_sync_wrote(&ctx->oy, nbytes);
248                 }
249                 ctx->have_more = true;
250                 serial = ogg_page_serialno(&ctx->ogg_page);
251                 if (ctx->stream_init) {
252                         if (serial != ctx->os.serialno)
253                                 ogg_stream_reset_serialno(&ctx->os, serial);
254                 } else {
255                         ogg_stream_init(&ctx->os, serial);
256                         ctx->stream_init = true;
257                 }
258                 /* Add page to the bitstream */
259                 ogg_stream_pagein(&ctx->os, &ctx->ogg_page);
260         }
261         ret = decode_packet(ctx, &op, btrn);
262         if (ret < 0)
263                 goto out;
264         ctx->packet_count++;
265         if (ctx->eos)
266                 ctx->have_opus_stream = false;
267 out:
268         if (ret < 0)
269                 btr_remove_node(&fn->btrn);
270         return ret;
271 }
272
273 static void opusdec_pre_select(struct sched *s, void *context)
274 {
275         struct filter_node *fn = context;
276         struct opusdec_context *ctx = fn->private_data;
277         int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
278
279         if (ret != 0)
280                 return sched_min_delay(s);
281         if (!ctx->have_more)
282                 return;
283         if (btr_get_output_queue_size(fn->btrn) <= OPUSDEC_MAX_OUTPUT_SIZE)
284                 return sched_min_delay(s);
285 }
286
287 /**
288  * The init function of the opusdec filter.
289  *
290  * \param f Pointer to the filter struct to initialize.
291  *
292  * \sa filter::init.
293  */
294 void opusdec_filter_init(struct filter *f)
295 {
296         f->open = opusdec_open;
297         f->close = opusdec_close;
298         f->pre_select = opusdec_pre_select;
299         f->post_select = opusdec_post_select;
300         f->execute = opusdec_execute;
301 }