1 /* Icecast
2  *
3  *  This program is distributed under the GNU General Public License,
4  *  version 2. A copy of this license is included with this source.
5  *  At your option, this specific source file can also be distributed
6  *  under the GNU GPL version 3.
7  *
8  * Copyright 2012,      David Richards, Mozilla Foundation,
9  *                      and others (see AUTHORS for details).
10  */
11 
12 
13 /* Ogg codec handler for opus streams */
14 
15 #ifdef HAVE_CONFIG_H
16 #include <config.h>
17 #endif
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ogg/ogg.h>
22 
23 typedef struct source_tag source_t;
24 
25 #include "format_opus.h"
26 #include "refbuf.h"
27 #include "client.h"
28 
29 #define CATMODULE "format-opus"
30 #include "logging.h"
31 
opus_codec_free(ogg_state_t * ogg_info,ogg_codec_t * codec)32 static void opus_codec_free (ogg_state_t *ogg_info, ogg_codec_t *codec)
33 {
34     ogg_stream_clear (&codec->os);
35     free (codec);
36 }
37 
38 
process_opus_page(ogg_state_t * ogg_info,ogg_codec_t * codec,ogg_page * page)39 static refbuf_t *process_opus_page (ogg_state_t *ogg_info,
40         ogg_codec_t *codec, ogg_page *page)
41 {
42     refbuf_t *refbuf;
43 
44     if (codec->headers < 2)
45     {
46         ogg_packet packet;
47 
48         ogg_stream_pagein (&codec->os, page);
49         while (ogg_stream_packetout (&codec->os, &packet) > 0)
50         {
51            /* first time around (normal case) yields comments */
52            codec->headers++;
53         }
54         /* add header page to associated list */
55         format_ogg_attach_header (ogg_info, page);
56         return NULL;
57     }
58     refbuf = make_refbuf_with_page (page);
59     return refbuf;
60 }
61 
62 
initial_opus_page(format_plugin_t * plugin,ogg_page * page)63 ogg_codec_t *initial_opus_page (format_plugin_t *plugin, ogg_page *page)
64 {
65     ogg_state_t *ogg_info = plugin->_state;
66     ogg_codec_t *codec = calloc (1, sizeof (ogg_codec_t));
67     ogg_packet packet;
68 
69     ogg_stream_init (&codec->os, ogg_page_serialno (page));
70     ogg_stream_pagein (&codec->os, page);
71 
72     ogg_stream_packetout (&codec->os, &packet);
73 
74     ICECAST_LOG_DEBUG("checking for opus codec");
75     if (packet.bytes < 8 || strncmp((char *)packet.packet, "OpusHead", 8) != 0)
76     {
77         ogg_stream_clear (&codec->os);
78         free (codec);
79         return NULL;
80     }
81     ICECAST_LOG_INFO("seen initial opus header");
82     codec->process_page = process_opus_page;
83     codec->codec_free = opus_codec_free;
84     codec->headers = 1;
85     codec->name = "Opus";
86     ogg_info->log_metadata = 1;
87     format_ogg_attach_header (ogg_info, page);
88     return codec;
89 }
90 
91