summaryrefslogtreecommitdiff
path: root/gst/mpegtsmux
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2015-10-25 17:27:39 +0200
committerSebastian Dröge <sebastian@centricular.com>2015-11-03 20:35:41 +0200
commite75a9edff1d5c7c4e01b4cd28d7bbf1bfb1fed0c (patch)
treec9d7bb02d014ddb8b7456c0f2d7973307420513f /gst/mpegtsmux
parent1e785a377846846929fec6745c967fd06396c30e (diff)
tsmux: Add support for Opus
https://bugzilla.gnome.org/show_bug.cgi?id=757049
Diffstat (limited to 'gst/mpegtsmux')
-rw-r--r--gst/mpegtsmux/Makefile.am6
-rw-r--r--gst/mpegtsmux/mpegtsmux.c92
-rw-r--r--gst/mpegtsmux/mpegtsmux_opus.c128
-rw-r--r--gst/mpegtsmux/mpegtsmux_opus.h91
-rw-r--r--gst/mpegtsmux/tsmux/tsmuxstream.c18
-rw-r--r--gst/mpegtsmux/tsmux/tsmuxstream.h5
6 files changed, 338 insertions, 2 deletions
diff --git a/gst/mpegtsmux/Makefile.am b/gst/mpegtsmux/Makefile.am
index 8e3cdba61..c9944f81b 100644
--- a/gst/mpegtsmux/Makefile.am
+++ b/gst/mpegtsmux/Makefile.am
@@ -5,7 +5,8 @@ SUBDIRS = tsmux
libgstmpegtsmux_la_SOURCES = \
mpegtsmux.c \
mpegtsmux_aac.c \
- mpegtsmux_ttxt.c
+ mpegtsmux_ttxt.c \
+ mpegtsmux_opus.c
libgstmpegtsmux_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS)
@@ -18,4 +19,5 @@ libgstmpegtsmux_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
noinst_HEADERS = \
mpegtsmux.h \
mpegtsmux_aac.h \
- mpegtsmux_ttxt.h
+ mpegtsmux_ttxt.h \
+ mpegtsmux_opus.h
diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c
index 9b7abfc87..0f6346b80 100644
--- a/gst/mpegtsmux/mpegtsmux.c
+++ b/gst/mpegtsmux/mpegtsmux.c
@@ -96,6 +96,7 @@
#include "mpegtsmux_aac.h"
#include "mpegtsmux_ttxt.h"
+#include "mpegtsmux_opus.h"
GST_DEBUG_CATEGORY (mpegtsmux_debug);
#define GST_CAT_DEFAULT mpegtsmux_debug
@@ -142,6 +143,7 @@ static GstStaticPadTemplate mpegtsmux_sink_factory =
"mute = (boolean) { FALSE, TRUE }; "
"audio/x-ac3, framed = (boolean) TRUE;"
"audio/x-dts, framed = (boolean) TRUE;"
+ "audio/x-opus;"
"subpicture/x-dvb; application/x-teletext; meta/x-klv, parsed=true"));
static GstStaticPadTemplate mpegtsmux_src_factory =
@@ -580,6 +582,7 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
const gchar *mt;
const GValue *value = NULL;
GstBuffer *codec_data = NULL;
+ guint8 opus_channel_config_code = 0;
pad = ts_data->collect.pad;
caps = gst_pad_get_current_caps (pad);
@@ -667,6 +670,93 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
st = TSMUX_ST_PS_TELETEXT;
/* needs a particularly sized layout */
ts_data->prepare_func = mpegtsmux_prepare_teletext;
+ } else if (strcmp (mt, "audio/x-opus") == 0) {
+ GstBuffer *streamheader = NULL;
+ const GValue *v;
+ GstMapInfo map;
+
+ v = gst_structure_get_value (s, "streamheader");
+ if (v && G_VALUE_HOLDS (v, GST_TYPE_ARRAY)
+ && gst_value_array_get_size (v) >= 1) {
+ const GValue *h = gst_value_array_get_value (v, 0);
+
+ streamheader = gst_value_get_buffer (h);
+ }
+
+ /* FIXME: We need to either map all values for the OpusHead header
+ * to caps, or always require/generate an OpusHead streamheader for the
+ * caps. E.g. in rtpopusdepay */
+ if (!streamheader || gst_buffer_get_size (streamheader) < 22) {
+ gint channels;
+
+ if (gst_structure_get_int (s, "channels", &channels) && channels <= 2) {
+ opus_channel_config_code = channels;
+ } else {
+ GST_FIXME_OBJECT (pad,
+ "Multichannel Opus without streamheader not handled");
+ goto not_negotiated;
+ }
+ }
+
+ gst_buffer_map (streamheader, &map, GST_MAP_READ);
+ if (map.data[9] == 2 && map.data[18] == 255 && map.data[19] == 1
+ && map.data[20] == 1) {
+ /* Dual mono */
+ opus_channel_config_code = 0;
+ } else if (map.data[9] >= 1 && map.data[9] <= 2 && map.data[18] == 0) {
+ /* RTP mapping */
+ opus_channel_config_code = map.data[9];
+ } else if (map.data[9] >= 2 && map.data[9] <= 8 && map.data[18] == 1
+ && map.size >= 21 + map.data[9]) {
+ static const guint8 coupled_stream_counts[9] = {
+ 1, 0, 1, 1, 2, 2, 2, 3, 3
+ };
+ static const guint8 channel_map_a[8][8] = {
+ {0},
+ {0, 1},
+ {0, 2, 1},
+ {0, 1, 2, 3},
+ {0, 4, 1, 2, 3},
+ {0, 4, 1, 2, 3, 5},
+ {0, 4, 1, 2, 3, 5, 6},
+ {0, 6, 1, 2, 3, 4, 5, 7},
+ };
+ static const guint8 channel_map_b[8][8] = {
+ {0},
+ {0, 1},
+ {0, 1, 2},
+ {0, 1, 2, 3},
+ {0, 1, 2, 3, 4},
+ {0, 1, 2, 3, 4, 5},
+ {0, 1, 2, 3, 4, 5, 6},
+ {0, 1, 2, 3, 4, 5, 6, 7},
+ };
+
+ /* Vorbis mapping */
+ if (map.data[19] == map.data[9] - coupled_stream_counts[map.data[9]] &&
+ map.data[20] == coupled_stream_counts[map.data[9]] &&
+ memcmp (&map.data[21], channel_map_a[map.data[9] - 1],
+ map.data[9]) == 0) {
+ opus_channel_config_code = map.data[9];
+ } else if (map.data[19] == map.data[9] &&
+ map.data[20] == 0 &&
+ memcmp (&map.data[21], channel_map_b[map.data[9] - 1],
+ map.data[9]) == 0) {
+ opus_channel_config_code = map.data[9] | 0x80;
+ } else {
+ gst_buffer_unmap (streamheader, &map);
+ GST_FIXME_OBJECT (pad, "Opus channel mapping not handled");
+ goto not_negotiated;
+ }
+ } else {
+ gst_buffer_unmap (streamheader, &map);
+ GST_FIXME_OBJECT (pad, "Opus channel mapping not handled");
+ goto not_negotiated;
+ }
+ gst_buffer_unmap (streamheader, &map);
+
+ st = TSMUX_ST_PS_OPUS;
+ ts_data->prepare_func = mpegtsmux_prepare_opus;
} else if (strcmp (mt, "meta/x-klv") == 0) {
st = TSMUX_ST_PS_KLV;
}
@@ -683,6 +773,8 @@ mpegtsmux_create_stream (MpegTsMux * mux, MpegTsPadData * ts_data)
gst_structure_get_int (s, "channels", &ts_data->stream->audio_channels);
gst_structure_get_int (s, "bitrate", &ts_data->stream->audio_bitrate);
+ ts_data->stream->opus_channel_config_code = opus_channel_config_code;
+
tsmux_stream_set_buffer_release_func (ts_data->stream, release_buffer_cb);
tsmux_program_add_stream (ts_data->prog, ts_data->stream);
diff --git a/gst/mpegtsmux/mpegtsmux_opus.c b/gst/mpegtsmux/mpegtsmux_opus.c
new file mode 100644
index 000000000..b64f8f52a
--- /dev/null
+++ b/gst/mpegtsmux/mpegtsmux_opus.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2006, 2007, 2008 Fluendo S.A.
+ * Authors: Jan Schmidt <jan@fluendo.com>
+ * Kapil Agrawal <kapil@fluendo.com>
+ * Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "mpegtsmux_opus.h"
+#include <string.h>
+
+#define GST_CAT_DEFAULT mpegtsmux_debug
+
+GstBuffer *
+mpegtsmux_prepare_opus (GstBuffer * buf, MpegTsPadData * pad_data,
+ MpegTsMux * mux)
+{
+ gssize insize = gst_buffer_get_size (buf);
+ gsize outsize;
+ GstBuffer *outbuf;
+ GstMapInfo map;
+ guint n;
+
+ /* TODO: Write start/end trim */
+ outsize = 2 + insize / 255 + 1;
+
+ outbuf = gst_buffer_new_and_alloc (outsize);
+ gst_buffer_copy_into (outbuf, buf,
+ GST_BUFFER_COPY_METADATA | GST_BUFFER_COPY_TIMESTAMPS, 0, 0);
+ gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
+ map.data[0] = 0x7f;
+ map.data[1] = 0xe0;
+ n = 2;
+ do {
+ g_assert (n < outsize);
+ /* FIXME: this should be using insize for writing here but ffmpeg and the
+ * only available sample stream from obe.tv are not including the control
+ * header size in au_size
+ */
+ map.data[n] = MIN (insize, 255);
+ insize -= 255;
+ n++;
+ } while (insize >= 0);
+
+ gst_buffer_unmap (outbuf, &map);
+
+ outbuf = gst_buffer_append (outbuf, gst_buffer_ref (buf));
+
+ return outbuf;
+}
diff --git a/gst/mpegtsmux/mpegtsmux_opus.h b/gst/mpegtsmux/mpegtsmux_opus.h
new file mode 100644
index 000000000..fdf25d884
--- /dev/null
+++ b/gst/mpegtsmux/mpegtsmux_opus.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2006, 2007, 2008 Fluendo S.A.
+ * Authors: Jan Schmidt <jan@fluendo.com>
+ * Kapil Agrawal <kapil@fluendo.com>
+ * Julien Moutte <julien@fluendo.com>
+ *
+ * This library is licensed under 4 different licenses and you
+ * can choose to use it under the terms of any one of them. The
+ * four licenses are the MPL 1.1, the LGPL, the GPL and the MIT
+ * license.
+ *
+ * MPL:
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/.
+ *
+ * Software distributed under the License is distributed on an "AS IS"
+ * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+ * License for the specific language governing rights and limitations
+ * under the License.
+ *
+ * LGPL:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * GPL:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * MIT:
+ *
+ * Unless otherwise indicated, Source Code is licensed under MIT license.
+ * See further explanation attached in License Statement (distributed in the file
+ * LICENSE).
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is furnished to do
+ * so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef __MPEGTSMUX_OPUS_H__
+#define __MPEGTSMUX_OPUS_H__
+
+#include "mpegtsmux.h"
+
+GstBuffer * mpegtsmux_prepare_opus (GstBuffer * buf, MpegTsPadData * data,
+ MpegTsMux * mux);
+
+#endif /* __MPEGTSMUX_OPUS_H__ */
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.c b/gst/mpegtsmux/tsmux/tsmuxstream.c
index 1094c3ea9..dd5752bf9 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.c
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.c
@@ -200,6 +200,13 @@ tsmux_stream_new (guint16 pid, TsMuxStreamType stream_type)
TSMUX_PACKET_FLAG_PES_FULL_HEADER |
TSMUX_PACKET_FLAG_PES_DATA_ALIGNMENT;
break;
+ case TSMUX_ST_PS_OPUS:
+ /* FIXME: assign sequential extended IDs? */
+ stream->id = 0xBD;
+ stream->stream_type = TSMUX_ST_PRIVATE_DATA;
+ stream->is_opus = TRUE;
+ stream->pi.flags |= TSMUX_PACKET_FLAG_PES_FULL_HEADER;
+ break;
default:
g_critical ("Stream type 0x%0x not yet implemented", stream_type);
break;
@@ -910,6 +917,17 @@ tsmux_stream_get_es_descrs (TsMuxStream * stream,
g_ptr_array_add (pmt_stream->descriptors, descriptor);
break;
}
+ if (stream->is_opus) {
+ descriptor = gst_mpegts_descriptor_from_registration ("Opus", NULL, 0);
+ g_ptr_array_add (pmt_stream->descriptors, descriptor);
+
+ descriptor =
+ gst_mpegts_descriptor_from_custom_with_extension
+ (GST_MTS_DESC_DVB_EXTENSION, 0x80,
+ &stream->opus_channel_config_code, 1);
+
+ g_ptr_array_add (pmt_stream->descriptors, descriptor);
+ }
if (stream->is_meta) {
descriptor = gst_mpegts_descriptor_from_registration ("KLVA", NULL, 0);
GST_ERROR ("adding KLVA registration descriptor!");
diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.h b/gst/mpegtsmux/tsmux/tsmuxstream.h
index c355ae2fc..26fe207d1 100644
--- a/gst/mpegtsmux/tsmux/tsmuxstream.h
+++ b/gst/mpegtsmux/tsmux/tsmuxstream.h
@@ -141,6 +141,7 @@ enum TsMuxStreamType {
TSMUX_ST_PS_DVB_SUBPICTURE = 0x8c,
TSMUX_ST_PS_TELETEXT = 0x8d,
TSMUX_ST_PS_KLV = 0x8e, /* only used internally */
+ TSMUX_ST_PS_OPUS = 0x8f, /* only used internally */
TSMUX_ST_PS_DVD_SUBPICTURE = 0xff,
/* Non-standard definitions */
@@ -209,6 +210,10 @@ struct TsMuxStream {
gchar language[4];
gboolean is_meta;
+
+ /* Opus */
+ gboolean is_opus;
+ guint8 opus_channel_config_code;
};
/* stream management */