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>
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
, struct task
*t
)
212 struct filter_node
*fn
= container_of(t
, struct filter_node
, task
);
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
, struct task
*t
)
274 struct filter_node
*fn
= container_of(t
, struct filter_node
, task
);
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
;