1 /* Icecast
2 *
3 * This program is distributed under the GNU General Public License, version 2.
4 * A copy of this license is included with this source.
5 *
6 * Copyright 2000-2004, Jack Moffitt <jack@xiph.org>,
7 * Michael Smith <msmith@xiph.org>,
8 * oddsock <oddsock@xiph.org>,
9 * Karl Heyes <karl@xiph.org>
10 * and others (see AUTHORS for details).
11 */
12
13
14 /* Ogg codec handler for speex streams */
15
16 #ifdef HAVE_CONFIG_H
17 #include <config.h>
18 #endif
19
20 #include <stdlib.h>
21 #include <ogg/ogg.h>
22 #include <speex/speex_header.h>
23
24 typedef struct source_tag source_t;
25
26 #include "format_speex.h"
27 #include "refbuf.h"
28 #include "client.h"
29
30 #define CATMODULE "format-speex"
31 #include "logging.h"
32
speex_codec_free(ogg_state_t * ogg_info,ogg_codec_t * codec)33 static void speex_codec_free (ogg_state_t *ogg_info, ogg_codec_t *codec)
34 {
35 ogg_stream_clear (&codec->os);
36 free (codec);
37 }
38
39
process_speex_page(ogg_state_t * ogg_info,ogg_codec_t * codec,ogg_page * page)40 static refbuf_t *process_speex_page (ogg_state_t *ogg_info,
41 ogg_codec_t *codec, ogg_page *page)
42 {
43 refbuf_t *refbuf;
44
45 if (codec->headers < 2)
46 {
47 ogg_packet packet;
48
49 ogg_stream_pagein (&codec->os, page);
50 while (ogg_stream_packetout (&codec->os, &packet) > 0)
51 {
52 /* first time around (normal case) yields comments */
53 codec->headers++;
54 }
55 /* add header page to associated list */
56 format_ogg_attach_header (ogg_info, page);
57 return NULL;
58 }
59 refbuf = make_refbuf_with_page (page);
60 return refbuf;
61 }
62
63
initial_speex_page(format_plugin_t * plugin,ogg_page * page)64 ogg_codec_t *initial_speex_page (format_plugin_t *plugin, ogg_page *page)
65 {
66 ogg_state_t *ogg_info = plugin->_state;
67 ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t));
68 ogg_packet packet;
69 SpeexHeader *header;
70
71 ogg_stream_init (&codec->os, ogg_page_serialno (page));
72 ogg_stream_pagein (&codec->os, page);
73
74 ogg_stream_packetout (&codec->os, &packet);
75
76 /* Check for te first packet to be at least of the minimal size for a Speex header.
77 * The header size is 80 bytes as per specs. You can find the specs here:
78 * https://speex.org/docs/manual/speex-manual/node8.html#SECTION00830000000000000000
79 *
80 * speex_packet_to_header() will also check the header size for us. However
81 * that function generates noise on stderr in case the header is too short.
82 * This is dangerous as we may have closed stderr already and the handle may be use
83 * again for something else.
84 */
85 if (packet.bytes < 80) {
86 return NULL;
87 }
88
89 ICECAST_LOG_DEBUG("checking for speex codec");
90 header = speex_packet_to_header ((char*)packet.packet, packet.bytes);
91 if (header == NULL)
92 {
93 ogg_stream_clear (&codec->os);
94 free (header);
95 free (codec);
96 return NULL;
97 }
98 ICECAST_LOG_INFO("seen initial speex header");
99 codec->process_page = process_speex_page;
100 codec->codec_free = speex_codec_free;
101 codec->headers = 1;
102 format_ogg_attach_header (ogg_info, page);
103 free (header);
104 return codec;
105 }
106