From 9d2a2750c2e69f1c687352e6b5b758add82dc77f Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Sat, 19 Nov 2011 16:06:09 +0000 Subject: [PATCH] ogg: add opus support --- ext/ogg/gstoggmux.c | 2 +- ext/ogg/gstoggstream.c | 85 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 186e87d55f..5341d6ca9a 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -107,7 +107,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d", "audio/x-vorbis; audio/x-flac; audio/x-speex; audio/x-celt; " "application/x-ogm-video; application/x-ogm-audio; video/x-dirac; " "video/x-smoke; video/x-vp8; text/x-cmml, encoded = (boolean) TRUE; " - "subtitle/x-kate; application/x-kate") + "subtitle/x-kate; application/x-kate; audio/x-opus") ); static void gst_ogg_mux_base_init (gpointer g_class); diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index a26791d261..08cfca76e0 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -1845,6 +1845,79 @@ extract_tags_kate (GstOggStream * pad, ogg_packet * packet) } } +/* opus */ + +static gboolean +setup_opus_mapper (GstOggStream * pad, ogg_packet * packet) +{ + if (packet->bytes < 19) + return FALSE; + + pad->granulerate_n = 48000; + pad->granulerate_d = 1; + pad->granuleshift = 0; + pad->n_header_packets = 2; + + pad->caps = gst_caps_new_simple ("audio/x-opus", NULL); + + return TRUE; +} + +static gint64 +packet_duration_opus (GstOggStream * pad, ogg_packet * packet) +{ + static const guint64 durations[32] = { + 10000, 20000, 40000, 60000, /* Silk NB */ + 10000, 20000, 40000, 60000, /* Silk MB */ + 10000, 20000, 40000, 60000, /* Silk WB */ + 10000, 20000, /* Hybrid SWB */ + 10000, 20000, /* Hybrid FB */ + 2500, 5000, 10000, 20000, /* CELT NB */ + 2500, 5000, 10000, 20000, /* CELT NB */ + 2500, 5000, 10000, 20000, /* CELT NB */ + 2500, 5000, 10000, 20000, /* CELT NB */ + }; + + gint64 duration; + gint64 frame_duration; + gint nframes; + guint8 toc; + + if (packet->bytes < 1) + return 0; + + toc = packet->packet[0]; + + frame_duration = durations[toc >> 3] * 1000; + switch (toc & 3) { + case 0: + nframes = 1; + break; + case 1: + nframes = 2; + break; + case 2: + nframes = 2; + break; + case 3: + if (packet->bytes < 2) { + GST_WARNING ("Code 3 Opus packet has less than 2 bytes"); + return 0; + } + nframes = packet->packet[1] & 63; + break; + } + + duration = nframes * frame_duration; + if (duration > 120 * GST_MSECOND) { + GST_WARNING ("Opus packet duration > 120 ms, invalid"); + return 0; + } + GST_LOG ("Opus packet: frame size %.1f ms, %d frames, duration %.1f ms", + frame_duration / 1000000.f, nframes, duration / 1000000.f); + return (duration + 24000) / 48000; +} + /* *INDENT-OFF* */ /* indent hates our freedoms */ @@ -2016,6 +2089,18 @@ const GstOggMap mappers[] = { granulepos_to_key_granule_vp8, extract_tags_vp8 }, + { + "OpusHead", 8, 0, + "audio/x-opus", + setup_opus_mapper, + granulepos_to_granule_default, + granule_to_granulepos_default, + NULL, + is_header_count, + packet_duration_opus, + NULL, + extract_tags_count + }, { "\001audio\0\0\0", 9, 53, "application/x-ogm-audio",