1 /* GStreamer
2  * Copyright (C) 2004 Wim Taymans <wim@fluendo.com>
3  * Copyright (C) 2006 Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>
5  * Copyright (C) <2011-2012> Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20  * Boston, MA 02110-1301, USA.
21  */
22 
23 /**
24  * SECTION:element-opusparse
25  * @title: opusparse
26  * @see_also: opusenc, opusdec
27  *
28  * This element parses OPUS packets.
29  *
30  * ## Example pipelines
31  * |[
32  * gst-launch-1.0 -v filesrc location=opusdata ! opusparse ! opusdec ! audioconvert ! audioresample ! alsasink
33  * ]| Decode and plays an unmuxed Opus file.
34  *
35  */
36 
37 #ifdef HAVE_CONFIG_H
38 #  include "config.h"
39 #endif
40 
41 #include <string.h>
42 #include <opus.h>
43 #include "gstopusheader.h"
44 #include "gstopusparse.h"
45 
46 #include <gst/audio/audio.h>
47 #include <gst/pbutils/pbutils.h>
48 
49 GST_DEBUG_CATEGORY_STATIC (opusparse_debug);
50 #define GST_CAT_DEFAULT opusparse_debug
51 
52 #define MAX_PAYLOAD_BYTES 1500
53 
54 static GstStaticPadTemplate opus_parse_src_factory =
55 GST_STATIC_PAD_TEMPLATE ("src",
56     GST_PAD_SRC,
57     GST_PAD_ALWAYS,
58     GST_STATIC_CAPS ("audio/x-opus, framed = (boolean) true")
59     );
60 
61 static GstStaticPadTemplate opus_parse_sink_factory =
62 GST_STATIC_PAD_TEMPLATE ("sink",
63     GST_PAD_SINK,
64     GST_PAD_ALWAYS,
65     GST_STATIC_CAPS ("audio/x-opus")
66     );
67 
68 G_DEFINE_TYPE (GstOpusParse, gst_opus_parse, GST_TYPE_BASE_PARSE);
69 
70 static gboolean gst_opus_parse_start (GstBaseParse * parse);
71 static gboolean gst_opus_parse_stop (GstBaseParse * parse);
72 static GstFlowReturn gst_opus_parse_handle_frame (GstBaseParse * base,
73     GstBaseParseFrame * frame, gint * skip);
74 static GstFlowReturn gst_opus_parse_parse_frame (GstBaseParse * base,
75     GstBaseParseFrame * frame);
76 
77 static void
gst_opus_parse_class_init(GstOpusParseClass * klass)78 gst_opus_parse_class_init (GstOpusParseClass * klass)
79 {
80   GstBaseParseClass *bpclass;
81   GstElementClass *element_class;
82 
83   bpclass = (GstBaseParseClass *) klass;
84   element_class = (GstElementClass *) klass;
85 
86   bpclass->start = GST_DEBUG_FUNCPTR (gst_opus_parse_start);
87   bpclass->stop = GST_DEBUG_FUNCPTR (gst_opus_parse_stop);
88   bpclass->handle_frame = GST_DEBUG_FUNCPTR (gst_opus_parse_handle_frame);
89 
90   gst_element_class_add_static_pad_template (element_class,
91       &opus_parse_src_factory);
92   gst_element_class_add_static_pad_template (element_class,
93       &opus_parse_sink_factory);
94   gst_element_class_set_static_metadata (element_class, "Opus audio parser",
95       "Codec/Parser/Audio", "parses opus audio streams",
96       "Vincent Penquerc'h <vincent.penquerch@collabora.co.uk>");
97 
98   GST_DEBUG_CATEGORY_INIT (opusparse_debug, "opusparse", 0,
99       "opus parsing element");
100 }
101 
102 static void
gst_opus_parse_init(GstOpusParse * parse)103 gst_opus_parse_init (GstOpusParse * parse)
104 {
105   parse->header_sent = FALSE;
106   parse->got_headers = FALSE;
107   parse->pre_skip = 0;
108 }
109 
110 static gboolean
gst_opus_parse_start(GstBaseParse * base)111 gst_opus_parse_start (GstBaseParse * base)
112 {
113   GstOpusParse *parse = GST_OPUS_PARSE (base);
114 
115   parse->header_sent = FALSE;
116   parse->got_headers = FALSE;
117   parse->pre_skip = 0;
118   parse->next_ts = 0;
119 
120   return TRUE;
121 }
122 
123 static gboolean
gst_opus_parse_stop(GstBaseParse * base)124 gst_opus_parse_stop (GstBaseParse * base)
125 {
126   GstOpusParse *parse = GST_OPUS_PARSE (base);
127 
128   parse->header_sent = FALSE;
129   parse->got_headers = FALSE;
130   parse->pre_skip = 0;
131 
132   return TRUE;
133 }
134 
135 static GstFlowReturn
gst_opus_parse_handle_frame(GstBaseParse * base,GstBaseParseFrame * frame,gint * skip)136 gst_opus_parse_handle_frame (GstBaseParse * base,
137     GstBaseParseFrame * frame, gint * skip)
138 {
139   GstOpusParse *parse;
140   guint8 *data;
141   gsize size;
142   guint32 packet_size;
143   int ret = FALSE;
144   const unsigned char *frames[48];
145   unsigned char toc;
146   short frame_sizes[48];
147   int payload_offset;
148   int packet_offset = 0;
149   gboolean is_header, is_idheader, is_commentheader;
150   GstMapInfo map;
151 
152   parse = GST_OPUS_PARSE (base);
153 
154   *skip = -1;
155 
156   gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
157   data = map.data;
158   size = map.size;
159   GST_DEBUG_OBJECT (parse,
160       "Checking for frame, %" G_GSIZE_FORMAT " bytes in buffer", size);
161 
162   /* check for headers */
163   is_idheader = gst_opus_header_is_id_header (frame->buffer);
164   is_commentheader = gst_opus_header_is_comment_header (frame->buffer);
165   is_header = is_idheader || is_commentheader;
166 
167   if (!is_header) {
168     int nframes;
169 
170     /* Next, check if there's an Opus packet there */
171     nframes =
172         opus_packet_parse (data, size, &toc, frames, frame_sizes,
173         &payload_offset);
174 
175     if (nframes < 0) {
176       /* Then, check for the test vector framing */
177       GST_DEBUG_OBJECT (parse,
178           "No Opus packet found, trying test vector framing");
179       if (size < 4) {
180         GST_DEBUG_OBJECT (parse, "Too small");
181         goto beach;
182       }
183       packet_size = GST_READ_UINT32_BE (data);
184       GST_DEBUG_OBJECT (parse, "Packet size: %u bytes", packet_size);
185       if (packet_size > MAX_PAYLOAD_BYTES) {
186         GST_DEBUG_OBJECT (parse, "Too large");
187         goto beach;
188       }
189       if (packet_size > size - 4) {
190         GST_DEBUG_OBJECT (parse, "Truncated");
191         goto beach;
192       }
193       nframes =
194           opus_packet_parse (data + 8, packet_size, &toc, frames, frame_sizes,
195           &payload_offset);
196       if (nframes < 0) {
197         GST_DEBUG_OBJECT (parse, "No test vector framing either");
198         goto beach;
199       }
200 
201       packet_offset = 8;
202 
203       /* for ad hoc framing, heed the framing, so we eat any padding */
204       payload_offset = packet_size;
205     } else {
206       /* Add up all the frame sizes found */
207       int f;
208       for (f = 0; f < nframes; ++f)
209         payload_offset += frame_sizes[f];
210     }
211   }
212 
213   if (is_header) {
214     *skip = 0;
215   } else {
216     *skip = packet_offset;
217     size = payload_offset;
218   }
219 
220   GST_DEBUG_OBJECT (parse,
221       "Got Opus packet at offset %d, %" G_GSIZE_FORMAT " bytes", *skip, size);
222   ret = TRUE;
223 
224 beach:
225   gst_buffer_unmap (frame->buffer, &map);
226 
227   /* convert old style result to new one */
228   if (!ret) {
229     if (*skip < 0)
230       *skip = 1;
231     return GST_FLOW_OK;
232   }
233 
234   /* always skip first if needed */
235   if (*skip > 0)
236     return GST_FLOW_OK;
237 
238   /* normalize again */
239   if (*skip < 0)
240     *skip = 0;
241 
242   /* not enough */
243   if (size > map.size)
244     return GST_FLOW_OK;
245 
246   /* FIXME some day ... should not mess with buffer itself */
247   if (!parse->got_headers) {
248     gst_buffer_replace (&frame->buffer,
249         gst_buffer_copy_region (frame->buffer, GST_BUFFER_COPY_ALL, 0, size));
250     gst_buffer_unref (frame->buffer);
251   }
252 
253   ret = gst_opus_parse_parse_frame (base, frame);
254 
255   if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
256     frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
257     ret = GST_FLOW_OK;
258   }
259   if (ret == GST_FLOW_OK)
260     ret = gst_base_parse_finish_frame (base, frame, size);
261 
262   return ret;
263 }
264 
265 /* Adapted copy of the one in gstoggstream.c... */
266 static guint64
packet_duration_opus(const guint8 * data,size_t len)267 packet_duration_opus (const guint8 * data, size_t len)
268 {
269   static const guint64 durations[32] = {
270     10000, 20000, 40000, 60000, /* Silk NB */
271     10000, 20000, 40000, 60000, /* Silk MB */
272     10000, 20000, 40000, 60000, /* Silk WB */
273     10000, 20000,               /* Hybrid SWB */
274     10000, 20000,               /* Hybrid FB */
275     2500, 5000, 10000, 20000,   /* CELT NB */
276     2500, 5000, 10000, 20000,   /* CELT NB */
277     2500, 5000, 10000, 20000,   /* CELT NB */
278     2500, 5000, 10000, 20000,   /* CELT NB */
279   };
280 
281   gint64 duration;
282   gint64 frame_duration;
283   gint nframes = 0;
284   guint8 toc;
285 
286   if (len < 1)
287     return 0;
288 
289   toc = data[0];
290 
291   frame_duration = durations[toc >> 3] * 1000;
292   switch (toc & 3) {
293     case 0:
294       nframes = 1;
295       break;
296     case 1:
297       nframes = 2;
298       break;
299     case 2:
300       nframes = 2;
301       break;
302     case 3:
303       if (len < 2) {
304         GST_WARNING ("Code 3 Opus packet has less than 2 bytes");
305         return 0;
306       }
307       nframes = data[1] & 63;
308       break;
309   }
310 
311   duration = nframes * frame_duration;
312   if (duration > 120 * GST_MSECOND) {
313     GST_WARNING ("Opus packet duration > 120 ms, invalid");
314     return 0;
315   }
316   GST_LOG ("Opus packet: frame size %.1f ms, %d frames, duration %.1f ms",
317       frame_duration / 1000000.f, nframes, duration / 1000000.f);
318   return duration;
319 }
320 
321 static GstFlowReturn
gst_opus_parse_parse_frame(GstBaseParse * base,GstBaseParseFrame * frame)322 gst_opus_parse_parse_frame (GstBaseParse * base, GstBaseParseFrame * frame)
323 {
324   guint64 duration;
325   GstOpusParse *parse;
326   gboolean is_idheader, is_commentheader;
327   GstMapInfo map;
328   GstAudioClippingMeta *cmeta =
329       gst_buffer_get_audio_clipping_meta (frame->buffer);
330 
331   parse = GST_OPUS_PARSE (base);
332 
333   g_assert (!cmeta || cmeta->format == GST_FORMAT_DEFAULT);
334 
335   is_idheader = gst_opus_header_is_id_header (frame->buffer);
336   is_commentheader = gst_opus_header_is_comment_header (frame->buffer);
337 
338   if (!parse->got_headers || !parse->header_sent) {
339     GstCaps *caps;
340 
341     /* Opus streams can decode to 1 or 2 channels, so use the header
342        value if we have one, or 2 otherwise */
343     if (is_idheader) {
344       gst_buffer_replace (&parse->id_header, frame->buffer);
345       GST_DEBUG_OBJECT (parse, "Found ID header, keeping");
346       return GST_BASE_PARSE_FLOW_DROPPED;
347     } else if (is_commentheader) {
348       gst_buffer_replace (&parse->comment_header, frame->buffer);
349       GST_DEBUG_OBJECT (parse, "Found comment header, keeping");
350       return GST_BASE_PARSE_FLOW_DROPPED;
351     }
352 
353     parse->got_headers = TRUE;
354 
355     if (cmeta && cmeta->start) {
356       parse->pre_skip += cmeta->start;
357 
358       gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
359       duration = packet_duration_opus (map.data, map.size);
360       gst_buffer_unmap (frame->buffer, &map);
361 
362       /* Queue frame for later once we know all initial padding */
363       if (duration == cmeta->start) {
364         frame->flags |= GST_BASE_PARSE_FRAME_FLAG_QUEUE;
365       }
366     }
367 
368     if (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_QUEUE)) {
369       GstCaps *sink_caps;
370       guint32 sample_rate = 48000;
371       guint8 n_channels, n_streams, n_stereo_streams, channel_mapping_family;
372       guint8 channel_mapping[256];
373       GstBuffer *id_header;
374       guint16 pre_skip = 0;
375       gint16 gain = 0;
376 
377       if (parse->id_header) {
378         gst_buffer_map (parse->id_header, &map, GST_MAP_READWRITE);
379         pre_skip = GST_READ_UINT16_LE (map.data + 10);
380         gain = GST_READ_UINT16_LE (map.data + 16);
381         gst_buffer_unmap (parse->id_header, &map);
382       }
383 
384       sink_caps = gst_pad_get_current_caps (GST_BASE_PARSE_SINK_PAD (parse));
385       if (!sink_caps
386           || !gst_codec_utils_opus_parse_caps (sink_caps, &sample_rate,
387               &n_channels, &channel_mapping_family, &n_streams,
388               &n_stereo_streams, channel_mapping)) {
389         GST_INFO_OBJECT (parse,
390             "No headers and no caps, blindly setting up canonical stereo");
391         n_channels = 2;
392         n_streams = 1;
393         n_stereo_streams = 1;
394         channel_mapping_family = 0;
395         channel_mapping[0] = 0;
396         channel_mapping[1] = 1;
397       }
398       if (sink_caps)
399         gst_caps_unref (sink_caps);
400 
401       id_header =
402           gst_codec_utils_opus_create_header (sample_rate, n_channels,
403           channel_mapping_family, n_streams, n_stereo_streams,
404           channel_mapping, pre_skip, gain);
405       caps = gst_codec_utils_opus_create_caps_from_header (id_header, NULL);
406       gst_buffer_unref (id_header);
407 
408       gst_buffer_replace (&parse->id_header, NULL);
409       gst_buffer_replace (&parse->comment_header, NULL);
410 
411       gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
412       gst_caps_unref (caps);
413       parse->header_sent = TRUE;
414     }
415   }
416 
417   GST_BUFFER_TIMESTAMP (frame->buffer) = parse->next_ts;
418 
419   gst_buffer_map (frame->buffer, &map, GST_MAP_READ);
420   duration = packet_duration_opus (map.data, map.size);
421   gst_buffer_unmap (frame->buffer, &map);
422   parse->next_ts += duration;
423 
424   GST_BUFFER_DURATION (frame->buffer) = duration;
425   GST_BUFFER_OFFSET_END (frame->buffer) =
426       gst_util_uint64_scale (parse->next_ts, 48000, GST_SECOND);
427   GST_BUFFER_OFFSET (frame->buffer) = parse->next_ts;
428 
429   return GST_FLOW_OK;
430 }
431