Introduce per group slice sizes.
[paraslash.git] / spxdec_filter.c
1 /*
2  * Copyright (C) 2002-2006 Jean-Marc Valin
3  * Copyright (C) 2010 Andre Noll <maan@systemlinux.org>
4  *
5  * Licensed under the GPL v2. For licencing details see COPYING.
6  */
7
8 /** \file spxdec_filter.c Paraslash's ogg/speex decoder. */
9
10 /* This file is based on speexdec.c, by Jean-Marc Valin, see below. */
11
12 /* Copyright (C) 2002-2006 Jean-Marc Valin
13    File: speexdec.c
14
15    Redistribution and use in source and binary forms, with or without
16    modification, are permitted provided that the following conditions
17    are met:
18    
19    - Redistributions of source code must retain the above copyright
20    notice, this list of conditions and the following disclaimer.
21    
22    - Redistributions in binary form must reproduce the above copyright
23    notice, this list of conditions and the following disclaimer in the
24    documentation and/or other materials provided with the distribution.
25    
26    - Neither the name of the Xiph.org Foundation nor the names of its
27    contributors may be used to endorse or promote products derived from
28    this software without specific prior written permission.
29    
30    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
33    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
34    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
35    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
36    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
37    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
38    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
39    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 */
42
43 #include <regex.h>
44 #include <ogg/ogg.h>
45 #include <speex/speex.h>
46 #include <stdbool.h>
47 #include <speex/speex_header.h>
48 #include <speex/speex_stereo.h>
49 #include <speex/speex_callbacks.h>
50
51 #include "para.h"
52 #include "list.h"
53 #include "sched.h"
54 #include "ggo.h"
55 #include "buffer_tree.h"
56 #include "filter.h"
57 #include "error.h"
58 #include "string.h"
59 #include "spx.h"
60
61 /** Data specific to the speexdec filter. */
62 struct private_spxdec_data {
63         /** Header information obtained from the first ogg packet. */
64         struct spx_header_info shi;
65         /** Read from and written to by the Speex routines. */
66         SpeexBits bits;
67         /* Ogg pages are retrieved from this structure. */
68         ogg_sync_state oy;
69         /** Extracted from header. */
70         int speex_serialno;
71         /** Total number of ogg packets retrieved so far. */
72         int packet_count;
73         /** Needed to find out how much to skip. */
74         ogg_int64_t last_granule;
75         /** Also needed for skipping packets. */
76         int lookahead;
77         /** The state information about the current stream. */
78         ogg_stream_state os;
79         /** Whether \a os initialized. */
80         bool stream_init;
81 };
82
83 static void spxdec_open(struct filter_node *fn)
84 {
85         struct private_spxdec_data *psd = para_calloc(sizeof(*psd));
86
87         fn->private_data = psd;
88         fn->min_iqs = 200;
89         psd->speex_serialno = -1;
90 }
91
92 static void speexdec_close(struct filter_node *fn)
93 {
94         struct private_spxdec_data *psd = fn->private_data;
95
96         if (psd->shi.state) {
97                 /* Destroy the decoder state */
98                 speex_decoder_destroy(psd->shi.state);
99                 /* Destroy the bit-stream struct */
100                 speex_bits_destroy(&psd->bits);
101         }
102         free(psd);
103         fn->private_data = NULL;
104 }
105
106 static int speexdec_execute(struct btr_node *btrn, const char *cmd,
107                 char **result)
108 {
109         struct filter_node *fn = btr_context(btrn);
110         struct private_spxdec_data *psd = fn->private_data;
111
112         return decoder_execute(cmd, psd->shi.sample_rate, psd->shi.channels,
113                 result);
114 }
115
116 static int speexdec_init(struct filter_node *fn)
117 {
118         struct private_spxdec_data *psd = fn->private_data;
119
120         PARA_INFO_LOG("init\n");
121         ogg_sync_init(&psd->oy);
122         speex_bits_init(&psd->bits);
123         return 1;
124 }
125
126 #if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
127 #define le_short(s) ((short) ((unsigned short) (s) << 8) | ((unsigned short) (s) >> 8))
128 #else
129 #define le_short(s) ((short) (s))
130 #endif
131
132 #define MAX_FRAME_SIZE 2000
133 /* Copy Ogg packet to Speex bitstream */
134 static int speexdec_write_frames(int packet_no,
135                 struct private_spxdec_data *psd, int skip_samples,
136                 int page_nb_packets, struct btr_node *btrn)
137 {
138         int i, j;
139
140         for (j = 0; j != psd->shi.nframes; j++) {
141                 short output[MAX_FRAME_SIZE], *btr_output;
142                 int skip = skip_samples + psd->lookahead, skip_idx = 0;
143                 int samples, new_frame_size = psd->shi.frame_size;
144
145                 if (speex_decode_int(psd->shi.state, &psd->bits, output) < 0)
146                         return -E_SPX_DECODE;
147                 if (speex_bits_remaining(&psd->bits) < 0)
148                         return -E_SPX_DECODE_OVERFLOW;
149                 if (psd->shi.channels == 2)
150                         speex_decode_stereo_int(output, psd->shi.frame_size,
151                                 &psd->shi.stereo);
152                 if (packet_no == 1 && j == 0 && skip_samples > 0) {
153                         new_frame_size -= skip;
154                         skip_idx = skip * psd->shi.channels;
155                 }
156                 if (packet_no == page_nb_packets && skip_samples < 0) {
157                         new_frame_size = psd->shi.nframes * psd->shi.frame_size
158                                 + skip - j * psd->shi.frame_size;
159                         if (new_frame_size < 0)
160                                 new_frame_size = 0;
161                         if (new_frame_size > psd->shi.frame_size)
162                                 new_frame_size = psd->shi.frame_size;
163                 }
164                 if (new_frame_size <= 0)
165                         continue;
166                 samples = new_frame_size * psd->shi.channels;
167                 btr_output = para_malloc(2 * samples);
168                 for (i = 0; i < samples; i++)
169                         btr_output[i] = le_short(output[i + skip_idx]);
170                 btr_add_output((char *)btr_output, samples * 2, btrn);
171         }
172         return 1;
173 }
174
175 /* Extract all available packets */
176 static int speexdec_extract_packets(struct private_spxdec_data *psd,
177                 ogg_stream_state *os, int skip_samples, int page_nb_packets,
178                 struct btr_node *btrn)
179 {
180         int ret, packet_no;
181         bool eos = false;
182
183         for (packet_no = 0;; psd->packet_count++) {
184                 ogg_packet op;
185
186                 if (ogg_stream_packetout(os, &op) != 1)
187                         return 0;
188                 if (op.bytes >= 5 && !memcmp(op.packet, "Speex", 5))
189                         psd->speex_serialno = os->serialno;
190                 if (psd->speex_serialno == -1)
191                         return 0;
192                 if (os->serialno != psd->speex_serialno)
193                         return 0;
194                 /* If first packet, process as Speex header */
195                 if (psd->packet_count == 0) {
196                         ret = spx_process_header(op.packet, op.bytes, &psd->shi);
197                         if (ret < 0)
198                                 return ret;
199                         ret = speex_decoder_ctl(psd->shi.state, SPEEX_GET_LOOKAHEAD,
200                                 &psd->lookahead);
201                         if (ret < 0)
202                                 return ret;
203                         if (!psd->shi.nframes)
204                                 psd->shi.nframes = 1;
205                         PARA_INFO_LOG("frame size: %d\n", psd->shi.frame_size);
206                         continue;
207                 }
208                 if (psd->packet_count == 1) /* ignore comments */
209                         continue;
210                 if (psd->packet_count <= 1 + psd->shi.extra_headers)
211                         continue; /* Ignore extra headers */
212                 packet_no++;
213                 /* check end of stream condition */
214                 if (op.e_o_s && os->serialno == psd->speex_serialno)
215                         eos = true;
216                 speex_bits_read_from(&psd->bits, (char *)op.packet,
217                         op.bytes);
218                 ret = speexdec_write_frames(packet_no, psd,
219                         skip_samples, page_nb_packets, btrn);
220                 if (ret < 0)
221                         return ret;
222                 if (eos == true)
223                         return -E_SPX_EOS;
224         }
225 }
226
227 static int compute_skip_samples(ogg_page *og, struct private_spxdec_data *psd)
228 {
229         int ret, page_granule = ogg_page_granulepos(og);
230
231         if (page_granule <= 0)
232                 return 0;
233         if (psd->shi.frame_size == 0)
234                 return 0;
235         ret = ogg_page_packets(og) * psd->shi.frame_size * psd->shi.nframes
236                 - page_granule + psd->last_granule;
237         if (ogg_page_eos(og))
238                 ret = -ret;
239         return ret;
240 }
241
242 static void speexdec_post_select(__a_unused struct sched *s, struct task *t)
243 {
244         struct filter_node *fn = container_of(t, struct filter_node, task);
245         struct private_spxdec_data *psd = fn->private_data;
246         struct btr_node *btrn = fn->btrn;
247         int ret, ns;
248         ogg_page og;
249         char *btr_buf;
250         size_t nbytes;
251
252 next_buffer:
253         t->error = 0;
254         ret = ns = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
255         btr_merge(btrn, fn->min_iqs);
256         if (!psd->shi.state) {
257                 if (ret <= 0)
258                         goto fail;
259                 ret = speexdec_init(fn);
260                 if (ret <= 0)
261                         goto fail;
262         }
263         nbytes = btr_next_buffer(btrn, &btr_buf);
264         nbytes = PARA_MIN(nbytes, (size_t)200);
265         if (nbytes > 0) {
266                 char *data = ogg_sync_buffer(&psd->oy, nbytes);
267                 memcpy(data, btr_buf, nbytes);
268                 btr_consume(btrn, nbytes);
269                 ogg_sync_wrote(&psd->oy, nbytes);
270         }
271         /* Loop for all complete pages we got */
272         while (ogg_sync_pageout(&psd->oy, &og) == 1) {
273                 int skip_samples;
274
275                 if (psd->stream_init == false) {
276                         ogg_stream_init(&psd->os, ogg_page_serialno(&og));
277                         psd->stream_init = true;
278                 }
279                 if (ogg_page_serialno(&og) != psd->os.serialno)
280                         ogg_stream_reset_serialno(&psd->os, ogg_page_serialno(&og));
281                 /* Add page to the bitstream */
282                 ogg_stream_pagein(&psd->os, &og);
283                 skip_samples = compute_skip_samples(&og, psd);
284                 psd->last_granule = ogg_page_granulepos(&og);
285                 ret = speexdec_extract_packets(psd, &psd->os, skip_samples,
286                         ogg_page_packets(&og), btrn);
287                 if (ret < 0)
288                         goto fail;
289         }
290         if (ns > 0)
291                 goto next_buffer;
292         ret = ns;
293 fail:
294         if (ret < 0) {
295                 t->error = ret;
296                 btr_remove_node(btrn);
297         }
298 }
299
300 /**
301  * The init function of the ogg/speex decoder.
302  *
303  * \param f Its fields are filled in by the function.
304  */
305 void spxdec_filter_init(struct filter *f)
306 {
307         f->open = spxdec_open;
308         f->close = speexdec_close;
309         f->pre_select = generic_filter_pre_select;
310         f->post_select = speexdec_post_select;
311         f->execute = speexdec_execute;
312 }