atom_data_free);
}
+AtomInfo *
+build_opus_extension (guint32 rate, guint8 channels, guint8 mapping_family,
+ guint8 stream_count, guint8 coupled_count, guint8 channel_mapping[256],
+ guint16 pre_skip, guint16 output_gain)
+{
+ AtomData *atom_data;
+ guint8 *data_block;
+ GstByteWriter bw;
+ gboolean hdl = TRUE;
+ guint data_block_len;
+
+ gst_byte_writer_init (&bw);
+ hdl &= gst_byte_writer_put_uint8 (&bw, 0x00); /* version number */
+ hdl &= gst_byte_writer_put_uint8 (&bw, channels);
+ hdl &= gst_byte_writer_put_uint16_le (&bw, pre_skip);
+ hdl &= gst_byte_writer_put_uint32_le (&bw, rate);
+ hdl &= gst_byte_writer_put_uint16_le (&bw, output_gain);
+ hdl &= gst_byte_writer_put_uint8 (&bw, mapping_family);
+ if (mapping_family > 0) {
+ hdl &= gst_byte_writer_put_uint8 (&bw, stream_count);
+ hdl &= gst_byte_writer_put_uint8 (&bw, coupled_count);
+ hdl &= gst_byte_writer_put_data (&bw, channel_mapping, channels);
+ }
+
+ if (!hdl) {
+ GST_WARNING ("Error creating header");
+ return NULL;
+ }
+
+ data_block_len = gst_byte_writer_get_size (&bw);
+ data_block = gst_byte_writer_reset_and_get_data (&bw);
+ atom_data = atom_data_new_from_data (FOURCC_dops, data_block, data_block_len);
+ g_free (data_block);
+
+ return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
+ atom_data_free);
+}
+
AtomInfo *
build_uuid_xmp_atom (GstBuffer * xmp_data)
{
AtomInfo * build_ac3_extension (guint8 fscod, guint8 bsid,
guint8 bsmod, guint8 acmod,
guint8 lfe_on, guint8 bitrate_code);
+AtomInfo * build_opus_extension (guint32 rate, guint8 channels, guint8 mapping_family,
+ guint8 stream_count, guint8 coupled_count,
+ guint8 channel_mapping[256], guint16 pre_skip,
+ guint16 output_gain);
+
AtomInfo * build_amr_extension (void);
AtomInfo * build_h263_extension (void);
AtomInfo * build_gama_atom (gdouble gamma);
#define FOURCC_mp4s GST_MAKE_FOURCC('m','p','4','s')
#define FOURCC_mp4v GST_MAKE_FOURCC('m','p','4','v')
#define FOURCC_name GST_MAKE_FOURCC('n','a','m','e')
+#define FOURCC_opus GST_MAKE_FOURCC('O','p','u','s')
+#define FOURCC_dops GST_MAKE_FOURCC('d','O','p','s')
#define FOURCC_pasp GST_MAKE_FOURCC('p','a','s','p')
#define FOURCC_pcst GST_MAKE_FOURCC('p','c','s','t')
#define FOURCC_pgap GST_MAKE_FOURCC('p','g','a','p')
#include <gst/audio/audio.h>
#include <gst/video/video.h>
#include <gst/tag/tag.h>
+#include <gst/pbutils/pbutils.h>
#include <sys/types.h>
#ifdef G_OS_WIN32
* the stream itself. Abuse the prepare_buf_func so we parse a frame
* and get the needed data */
qtpad->prepare_buf_func = gst_qt_mux_prepare_parse_ac3_frame;
+ } else if (strcmp (mimetype, "audio/x-opus") == 0) {
+ /* Based on the specification defined in:
+ * https://www.opus-codec.org/docs/opus_in_isobmff.html */
+ guint8 channels, mapping_family, stream_count, coupled_count;
+ guint16 pre_skip;
+ gint16 output_gain;
+ guint32 rate;
+ guint8 channel_mapping[256];
+ const GValue *streamheader;
+ const GValue *first_element;
+ GstBuffer *header;
+
+ entry.fourcc = FOURCC_opus;
+ entry.sample_size = 16;
+
+ streamheader = gst_structure_get_value (structure, "streamheader");
+ if (streamheader && GST_VALUE_HOLDS_ARRAY (streamheader) &&
+ gst_value_array_get_size (streamheader) != 0) {
+ first_element = gst_value_array_get_value (streamheader, 0);
+ header = gst_value_get_buffer (first_element);
+ if (!gst_codec_utils_opus_parse_header (header, &rate, &channels,
+ &mapping_family, &stream_count, &coupled_count, channel_mapping,
+ &pre_skip, &output_gain)) {
+ GST_ERROR_OBJECT (qtmux, "Incomplete OpusHead");
+ goto refuse_caps;
+ }
+ } else {
+ GST_WARNING_OBJECT (qtmux,
+ "no streamheader field in caps %" GST_PTR_FORMAT, caps);
+
+ if (!gst_codec_utils_opus_parse_caps (caps, &rate, &channels,
+ &mapping_family, &stream_count, &coupled_count,
+ channel_mapping)) {
+ GST_ERROR_OBJECT (qtmux, "Incomplete Opus caps");
+ goto refuse_caps;
+ }
+ pre_skip = 0;
+ output_gain = 0;
+ }
+
+ entry.channels = channels;
+ ext_atom = build_opus_extension (rate, channels, mapping_family,
+ stream_count, coupled_count, channel_mapping, pre_skip, output_gain);
}
if (!entry.fourcc)
"audio/x-alac, " \
COMMON_AUDIO_CAPS(2, MAX)
+#define OPUS_CAPS \
+ "audio/x-opus, " \
+ "channel-mapping-family = (int) [0, 255], " \
+ COMMON_AUDIO_CAPS(8, MAX)
+
+
#define TEXT_UTF8 \
"text/x-raw, " \
"format=(string)utf8"
GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
"video/x-mp4-part," COMMON_VIDEO_CAPS),
- GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS " ; " AC3_CAPS " ; " ALAC_CAPS),
+ GST_STATIC_CAPS (MP3_CAPS "; "
+ AAC_CAPS " ; " AC3_CAPS " ; " ALAC_CAPS " ; " OPUS_CAPS),
GST_STATIC_CAPS (TEXT_UTF8)}
,
/* Microsoft Smooth Streaming fmp4/isml */