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>
7 * Licensed under the GPL v2. For licencing details see COPYING.
10 /** \file opusdec_filter.c The ogg/opus decoder. */
12 /* This file is based on opusdec.c, by Jean-Marc Valin, see below. */
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions are met:
18 * - Redistributions of source code must retain the above copyright notice,
19 * this list of conditions and the following disclaimer.
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.
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.
39 /* Silence gcc warning caused by including opus.h */
40 #if !defined(__STDC_VERSION__)
41 #define __STDC_VERSION__ 0
45 #include <opus/opus.h>
46 #include <opus/opus_multistream.h>
54 #include "buffer_tree.h"
58 #include "opus_common.h"
61 #define MAX_FRAME_SIZE (960*6)
63 struct opusdec_context {
65 opus_int64 packet_count;
74 bool have_opus_stream;
76 ogg_int32_t opus_serialno;
79 static int opusdec_execute(struct btr_node *btrn, const char *cmd,
82 struct filter_node *fn = btr_context(btrn);
83 struct opusdec_context *ctx = fn->private_data;
85 return decoder_execute(cmd, 48000, ctx->channels, result);
88 static void opusdec_open(struct filter_node *fn)
90 struct opusdec_context *ctx = para_calloc(sizeof(*ctx));
92 ogg_sync_init(&ctx->oy);
93 fn->private_data = ctx;
96 static void opusdec_close(struct filter_node *fn)
98 struct opusdec_context *ctx = fn->private_data;
101 opus_multistream_decoder_destroy(ctx->st);
102 if (ctx->stream_init)
103 ogg_stream_clear(&ctx->os);
104 ogg_sync_clear(&ctx->oy);
107 fn->private_data = NULL;
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)
114 struct opus_header header;
117 ret = opus_parse_header((char *)op->packet, op->bytes, &header);
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;
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;
136 PARA_INFO_LOG("playback gain: %fdB\n", header.gain / 256.);
138 PARA_INFO_LOG("%d channel(s), 48KHz\n", ctx->channels);
142 static void opusdec_add_output(short *pcm, int frames_available,
143 struct btr_node *btrn, struct opusdec_context *ctx)
145 int tmp_skip, num_frames, bytes;
147 tmp_skip = PARA_MIN(ctx->preskip, frames_available);
148 ctx->preskip -= tmp_skip;
149 num_frames = frames_available - tmp_skip;
152 bytes = sizeof(short) * num_frames * ctx->channels;
155 short *in = pcm + ctx->channels * tmp_skip;
156 short *out = para_malloc(bytes);
157 memcpy(out, in, bytes);
161 btr_add_output((char *)pcm, bytes, btrn);
164 /* returns > 1 if packet was decoded, 0 if it was ignored, negative on errors. */
165 static int decode_packet(struct opusdec_context *ctx, ogg_packet *op,
166 struct btr_node *btrn)
172 * OggOpus streams are identified by a magic string in the initial
175 if (op->b_o_s && op->bytes >= 8 && !memcmp(op->packet, "OpusHead", 8)) {
176 if (!ctx->have_opus_stream) {
177 ctx->opus_serialno = ctx->os.serialno;
178 ctx->have_opus_stream = true;
179 ctx->packet_count = 0;
183 PARA_NOTICE_LOG("ignoring opus stream %llu\n",
184 (long long unsigned)ctx->os.serialno);
186 if (!ctx->have_opus_stream || ctx->os.serialno != ctx->opus_serialno)
188 /* If first packet in a logical stream, process the Opus header. */
189 if (ctx->packet_count == 0)
190 return opusdec_init(op, ctx);
191 if (ctx->packet_count == 1)
193 /* don't care for anything except opus eos */
194 if (op->e_o_s && ctx->os.serialno == ctx->opus_serialno)
196 output = para_malloc(sizeof(short) * MAX_FRAME_SIZE * ctx->channels);
197 ret = opus_multistream_decode(ctx->st, (unsigned char *)op->packet,
198 op->bytes, output, MAX_FRAME_SIZE, 0);
200 PARA_ERROR_LOG("%s\n", opus_strerror(ret));
202 return -E_OPUS_DECODE;
204 opusdec_add_output(output, ret, btrn, ctx);
208 #define OPUSDEC_MAX_OUTPUT_SIZE (1024 * 1024)
210 static int opusdec_post_select(__a_unused struct sched *s, void *context)
212 struct filter_node *fn = context;
213 struct opusdec_context *ctx = fn->private_data;
214 struct btr_node *btrn = fn->btrn;
218 ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
220 if (ret != -E_BTR_EOF) /* fatal error */
222 if (!ctx->have_more) /* EOF */
224 } else if (ret == 0 && !ctx->have_more) /* nothing to do */
226 if (btr_get_output_queue_size(btrn) > OPUSDEC_MAX_OUTPUT_SIZE)
230 if (ctx->stream_init) {
231 ret = ogg_stream_packetout(&ctx->os, &op);
235 while (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1) {
236 char *btr_buf, *data;
237 size_t nbytes = btr_next_buffer(btrn, &btr_buf);
238 nbytes = PARA_MIN(nbytes, (size_t)24 * 1024);
239 //PARA_CRIT_LOG("nbytes: %d\n", nbytes);
240 ctx->have_more = false;
243 data = ogg_sync_buffer(&ctx->oy, nbytes);
244 memcpy(data, btr_buf, nbytes);
245 btr_consume(btrn, nbytes);
246 ogg_sync_wrote(&ctx->oy, nbytes);
248 ctx->have_more = true;
249 serial = ogg_page_serialno(&ctx->ogg_page);
250 if (ctx->stream_init) {
251 if (serial != ctx->os.serialno)
252 ogg_stream_reset_serialno(&ctx->os, serial);
254 ogg_stream_init(&ctx->os, serial);
255 ctx->stream_init = true;
257 /* Add page to the bitstream */
258 ogg_stream_pagein(&ctx->os, &ctx->ogg_page);
260 ret = decode_packet(ctx, &op, btrn);
265 ctx->have_opus_stream = false;
268 btr_remove_node(&fn->btrn);
272 static void opusdec_pre_select(struct sched *s, void *context)
274 struct filter_node *fn = context;
275 struct opusdec_context *ctx = fn->private_data;
276 int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
279 return sched_min_delay(s);
282 if (btr_get_output_queue_size(fn->btrn) <= OPUSDEC_MAX_OUTPUT_SIZE)
283 return sched_min_delay(s);
287 * The init function of the opusdec filter.
289 * \param f Pointer to the filter struct to initialize.
293 void opusdec_filter_init(struct filter *f)
295 f->open = opusdec_open;
296 f->close = opusdec_close;
297 f->pre_select = opusdec_pre_select;
298 f->post_select = opusdec_post_select;
299 f->execute = opusdec_execute;