afh: Initialize audio format handlers only once.
[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-2013 Andre Noll <maan@systemlinux.org>
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 #include <regex.h>
39 #include <opus/opus.h>
40 #include <opus/opus_multistream.h>
41 #include <ogg/ogg.h>
42 #include <math.h>
43
44 #include "para.h"
45 #include "list.h"
46 #include "sched.h"
47 #include "ggo.h"
48 #include "buffer_tree.h"
49 #include "filter.h"
50 #include "error.h"
51 #include "string.h"
52 #include "opus_common.h"
53
54 /** 120ms at 48000 */
55 #define MAX_FRAME_SIZE (960*6)
56
57 struct opusdec_context {
58         OpusMSDecoder *st;
59         opus_int64 packet_count;
60         int total_links;
61         bool stream_init;
62         ogg_sync_state oy;
63         ogg_stream_state os;
64         ogg_page ogg_page;
65         bool eos;
66         int channels;
67         int preskip;
68         bool have_opus_stream;
69         ogg_int32_t opus_serialno;
70 };
71
72 static int opusdec_execute(struct btr_node *btrn, const char *cmd,
73                 char **result)
74 {
75         struct filter_node *fn = btr_context(btrn);
76         struct opusdec_context *ctx = fn->private_data;
77
78         return decoder_execute(cmd, 48000, ctx->channels, result);
79 }
80
81 static void opusdec_open(struct filter_node *fn)
82 {
83         struct opusdec_context *ctx = para_calloc(sizeof(*ctx));
84
85         ogg_sync_init(&ctx->oy);
86         fn->private_data = ctx;
87 }
88
89 static void opusdec_close(struct filter_node *fn)
90 {
91         struct opusdec_context *ctx = fn->private_data;
92
93         if (ctx->st) {
94                 opus_multistream_decoder_destroy(ctx->st);
95                 if (ctx->stream_init)
96                         ogg_stream_clear(&ctx->os);
97                 ogg_sync_clear(&ctx->oy);
98         }
99         free(ctx);
100         fn->private_data = NULL;
101 }
102
103 /* Process an Opus header and setup the opus decoder based on it. */
104 static int opusdec_init(ogg_packet *op, struct opusdec_context *ctx)
105 {
106         int ret;
107         struct opus_header header;
108
109         ctx->st = NULL;
110         ret = opus_parse_header((char *)op->packet, op->bytes, &header);
111         if (ret < 0)
112                 return ret;
113         PARA_INFO_LOG("detected header v%d\n", header.version);
114         ctx->channels = header.channels;
115         ctx->preskip = header.preskip;
116         ctx->st = opus_multistream_decoder_create(48000, header.channels,
117                 header.nb_streams, header.nb_coupled, header.stream_map, &ret);
118         if (ret != OPUS_OK || !ctx->st) {
119                 PARA_ERROR_LOG("%s\n", opus_strerror(ret));
120                 return -E_CREATE_OPUS_DECODER;
121         }
122         if (header.gain != 0) {
123                 ret = opus_multistream_decoder_ctl(ctx->st,
124                         OPUS_SET_GAIN(header.gain));
125                 if (ret != OPUS_OK) {
126                         PARA_ERROR_LOG("%s\n", opus_strerror(ret));
127                         return -E_OPUS_SET_GAIN;
128                 }
129                 PARA_INFO_LOG("playback gain: %fdB\n", header.gain / 256.);
130         }
131         PARA_INFO_LOG("%d channel(s), 48KHz\n", ctx->channels);
132         return 1;
133 }
134
135 static void opusdec_add_output(short *pcm, int frames_available,
136                 struct btr_node *btrn, struct opusdec_context *ctx)
137 {
138         int tmp_skip, num_frames, bytes;
139
140         tmp_skip = PARA_MIN(ctx->preskip, frames_available);
141         ctx->preskip -= tmp_skip;
142         num_frames = frames_available - tmp_skip;
143         if (num_frames <= 0)
144                 return;
145         bytes = sizeof(short) * num_frames * ctx->channels;
146
147         if (tmp_skip > 0) {
148                 short *in = pcm + ctx->channels * tmp_skip;
149                 short *out = para_malloc(bytes);
150                 memcpy(out, in, bytes);
151                 free(pcm);
152                 pcm = out;
153         }
154         btr_add_output((char *)pcm, bytes, btrn);
155 }
156
157 /* returns > 1 if packet was decoded, 0 if it was ignored, negative on errors. */
158 static int decode_packet(struct opusdec_context *ctx, ogg_packet *op,
159                 struct btr_node *btrn)
160 {
161         int ret;
162         short *output;
163
164         /*
165          * OggOpus streams are identified by a magic string in the initial
166          * stream header.
167          */
168         if (op->b_o_s && op->bytes >= 8 && !memcmp(op->packet, "OpusHead", 8)) {
169                 if (!ctx->have_opus_stream) {
170                         ctx->opus_serialno = ctx->os.serialno;
171                         ctx->have_opus_stream = true;
172                         ctx->packet_count = 0;
173                         ctx->eos = false;
174                         ctx->total_links++;
175                 } else
176                         PARA_NOTICE_LOG("ignoring opus stream %llu\n",
177                                 (long long unsigned)ctx->os.serialno);
178         }
179         if (!ctx->have_opus_stream || ctx->os.serialno != ctx->opus_serialno)
180                 return 0;
181         /* If first packet in a logical stream, process the Opus header. */
182         if (ctx->packet_count == 0)
183                 return opusdec_init(op, ctx);
184         if (ctx->packet_count == 1)
185                 return 1;
186         /* don't care for anything except opus eos */
187         if (op->e_o_s && ctx->os.serialno == ctx->opus_serialno)
188                 ctx->eos = true;
189         output = para_malloc(sizeof(short) * MAX_FRAME_SIZE * ctx->channels);
190         ret = opus_multistream_decode(ctx->st, (unsigned char *)op->packet,
191                 op->bytes, output, MAX_FRAME_SIZE, 0);
192         if (ret < 0) {
193                 PARA_ERROR_LOG("%s\n", opus_strerror(ret));
194                 free(output);
195                 return -E_OPUS_DECODE;
196         }
197         opusdec_add_output(output, ret, btrn, ctx);
198         return 1;
199 }
200
201 static void opusdec_pre_select(struct sched *s, struct task *t)
202 {
203         struct filter_node *fn = container_of(t, struct filter_node, task);
204         struct btr_node *btrn = fn->btrn;
205         int ns;
206
207         ns = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
208         if (ns != 0)
209                 return sched_min_delay(s);
210         sched_request_timeout_ms(100, s);
211 }
212
213 static int opusdec_post_select(__a_unused struct sched *s, struct task *t)
214 {
215         struct filter_node *fn = container_of(t, struct filter_node, task);
216         struct opusdec_context *ctx = fn->private_data;
217         struct btr_node *btrn = fn->btrn;
218         int ret;
219         char *btr_buf, *data;
220         size_t nbytes;
221         ogg_packet op;
222
223         ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
224         if (ret <= 0)
225                 goto out;
226         btr_merge(btrn, fn->min_iqs);
227         nbytes = btr_next_buffer(btrn, &btr_buf);
228         nbytes = PARA_MIN(nbytes, (size_t)32768);
229         ret = 0;
230         if (nbytes == 0)
231                 goto out;
232         data = ogg_sync_buffer(&ctx->oy, nbytes);
233         memcpy(data, btr_buf, nbytes);
234         btr_consume(btrn, nbytes);
235         ogg_sync_wrote(&ctx->oy, nbytes);
236         for (;;) { /* loop over all ogg pages we got */
237                 ret = 0;
238                 if (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1)
239                         goto out;
240                 if (!ctx->stream_init) {
241                         ogg_stream_init(&ctx->os, ogg_page_serialno(&ctx->ogg_page));
242                         ctx->stream_init = true;
243                 }
244                 if (ogg_page_serialno(&ctx->ogg_page) != ctx->os.serialno)
245                         ogg_stream_reset_serialno(&ctx->os,
246                                 ogg_page_serialno(&ctx->ogg_page));
247                 /* Add page to the bitstream */
248                 ogg_stream_pagein(&ctx->os, &ctx->ogg_page);
249                 for (;;) { /* loop over all opus packets */
250                         ret = ogg_stream_packetout(&ctx->os, &op);
251                         if (ret != 1)
252                                 break;
253                         ret = decode_packet(ctx, &op, btrn);
254                         if (ret < 0)
255                                 goto out;
256                         ctx->packet_count++;
257                         if (ctx->eos)
258                                 ctx->have_opus_stream = false;
259                 }
260         }
261 out:
262         if (ret < 0)
263                 btr_remove_node(&fn->btrn);
264         return ret;
265 }
266
267 /**
268  * The init function of the opusdec filter.
269  *
270  * \param f Pointer to the filter struct to initialize.
271  *
272  * \sa filter::init.
273  */
274 void opusdec_filter_init(struct filter *f)
275 {
276         f->open = opusdec_open;
277         f->close = opusdec_close;
278         f->pre_select = generic_filter_pre_select;
279         f->pre_select = opusdec_pre_select;
280         f->post_select = opusdec_post_select;
281         f->execute = opusdec_execute;
282 }