/* GStreamer * Copyright (C) <2012> Wim Taymans * * 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. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "audio-format.h" #include "gstaudiopack.h" #ifdef HAVE_ORC #include #else #define orc_memset memset #endif #if G_BYTE_ORDER == G_LITTLE_ENDIAN # define audio_orc_unpack_s16le audio_orc_unpack_s16 # define audio_orc_unpack_s16le_trunc audio_orc_unpack_s16_trunc # define audio_orc_unpack_s16be audio_orc_unpack_s16_swap # define audio_orc_unpack_s16be_trunc audio_orc_unpack_s16_swap_trunc # define audio_orc_unpack_u16le audio_orc_unpack_u16 # define audio_orc_unpack_u16le_trunc audio_orc_unpack_u16_trunc # define audio_orc_unpack_u16be audio_orc_unpack_u16_swap # define audio_orc_unpack_u16be_trunc audio_orc_unpack_u16_swap_trunc # define audio_orc_unpack_s24_32le audio_orc_unpack_s24_32 # define audio_orc_unpack_s24_32be audio_orc_unpack_s24_32_swap # define audio_orc_unpack_u24_32le audio_orc_unpack_u24_32 # define audio_orc_unpack_u24_32be audio_orc_unpack_u24_32_swap # define audio_orc_unpack_s32le audio_orc_unpack_s32 # define audio_orc_unpack_s32be audio_orc_unpack_s32_swap # define audio_orc_unpack_u32le audio_orc_unpack_u32 # define audio_orc_unpack_u32be audio_orc_unpack_u32_swap # define audio_orc_unpack_f32le audio_orc_unpack_f32 # define audio_orc_unpack_f32be audio_orc_unpack_f32_swap # define audio_orc_unpack_f64le audio_orc_unpack_f64 # define audio_orc_unpack_f64be audio_orc_unpack_f64_swap # define audio_orc_pack_s16le audio_orc_pack_s16 # define audio_orc_pack_s16be audio_orc_pack_s16_swap # define audio_orc_pack_u16le audio_orc_pack_u16 # define audio_orc_pack_u16be audio_orc_pack_u16_swap # define audio_orc_pack_s24_32le audio_orc_pack_s24_32 # define audio_orc_pack_s24_32be audio_orc_pack_s24_32_swap # define audio_orc_pack_u24_32le audio_orc_pack_u24_32 # define audio_orc_pack_u24_32be audio_orc_pack_u24_32_swap # define audio_orc_pack_s32le audio_orc_pack_s32 # define audio_orc_pack_s32be audio_orc_pack_s32_swap # define audio_orc_pack_u32le audio_orc_pack_u32 # define audio_orc_pack_u32be audio_orc_pack_u32_swap # define audio_orc_pack_f32le audio_orc_pack_f32 # define audio_orc_pack_f32be audio_orc_pack_f32_swap # define audio_orc_pack_f64le audio_orc_pack_f64 # define audio_orc_pack_f64be audio_orc_pack_f64_swap #else # define audio_orc_unpack_s16le audio_orc_unpack_s16_swap # define audio_orc_unpack_s16le_trunc audio_orc_unpack_s16_swap_trunc # define audio_orc_unpack_s16be audio_orc_unpack_s16 # define audio_orc_unpack_s16be_trunc audio_orc_unpack_s16_trunc # define audio_orc_unpack_u16le audio_orc_unpack_u16_swap # define audio_orc_unpack_u16le_trunc audio_orc_unpack_u16_swap_trunc # define audio_orc_unpack_u16be audio_orc_unpack_u16 # define audio_orc_unpack_u16be_trunc audio_orc_unpack_u16_trunc # define audio_orc_unpack_s24_32le audio_orc_unpack_s24_32_swap # define audio_orc_unpack_s24_32be audio_orc_unpack_s24_32 # define audio_orc_unpack_u24_32le audio_orc_unpack_u24_32_swap # define audio_orc_unpack_u24_32be audio_orc_unpack_u24_32 # define audio_orc_unpack_s32le audio_orc_unpack_s32_swap # define audio_orc_unpack_s32be audio_orc_unpack_s32 # define audio_orc_unpack_u32le audio_orc_unpack_u32_swap # define audio_orc_unpack_u32be audio_orc_unpack_u32 # define audio_orc_unpack_f32le audio_orc_unpack_f32_swap # define audio_orc_unpack_f32be audio_orc_unpack_f32 # define audio_orc_unpack_f64le audio_orc_unpack_f64_swap # define audio_orc_unpack_f64be audio_orc_unpack_f64 # define audio_orc_pack_s16le audio_orc_pack_s16_swap # define audio_orc_pack_s16be audio_orc_pack_s16 # define audio_orc_pack_u16le audio_orc_pack_u16_swap # define audio_orc_pack_u16be audio_orc_pack_u16 # define audio_orc_pack_s24_32le audio_orc_pack_s24_32_swap # define audio_orc_pack_s24_32be audio_orc_pack_s24_32 # define audio_orc_pack_u24_32le audio_orc_pack_u24_32_swap # define audio_orc_pack_u24_32be audio_orc_pack_u24_32 # define audio_orc_pack_s32le audio_orc_pack_s32_swap # define audio_orc_pack_s32be audio_orc_pack_s32 # define audio_orc_pack_u32le audio_orc_pack_u32_swap # define audio_orc_pack_u32be audio_orc_pack_u32 # define audio_orc_pack_f32le audio_orc_pack_f32_swap # define audio_orc_pack_f32be audio_orc_pack_f32 # define audio_orc_pack_f64le audio_orc_pack_f64_swap # define audio_orc_pack_f64be audio_orc_pack_f64 #endif #define MAKE_ORC_PACK_UNPACK(fmt,fmt_t) \ static void unpack_ ##fmt (const GstAudioFormatInfo *info, \ GstAudioPackFlags flags, gpointer dest, \ gconstpointer data, gint length) { \ if (flags & GST_AUDIO_PACK_FLAG_TRUNCATE_RANGE) \ audio_orc_unpack_ ##fmt_t (dest, data, length); \ else \ audio_orc_unpack_ ##fmt (dest, data, length); \ } \ static void pack_ ##fmt (const GstAudioFormatInfo *info, \ GstAudioPackFlags flags, gconstpointer src, \ gpointer data, gint length) { \ audio_orc_pack_ ##fmt (data, src, length); \ } #define PACK_S8 GST_AUDIO_FORMAT_S32, unpack_s8, pack_s8 MAKE_ORC_PACK_UNPACK (s8, s8_trunc) #define PACK_U8 GST_AUDIO_FORMAT_S32, unpack_u8, pack_u8 MAKE_ORC_PACK_UNPACK (u8, u8_trunc) #define PACK_S16LE GST_AUDIO_FORMAT_S32, unpack_s16le, pack_s16le MAKE_ORC_PACK_UNPACK (s16le, s16le_trunc) #define PACK_S16BE GST_AUDIO_FORMAT_S32, unpack_s16be, pack_s16be MAKE_ORC_PACK_UNPACK (s16be, s16be_trunc) #define PACK_U16LE GST_AUDIO_FORMAT_S32, unpack_u16le, pack_u16le MAKE_ORC_PACK_UNPACK (u16le, u16le_trunc) #define PACK_U16BE GST_AUDIO_FORMAT_S32, unpack_u16be, pack_u16be MAKE_ORC_PACK_UNPACK (u16be, u16be_trunc) #define PACK_S24_32LE GST_AUDIO_FORMAT_S32, unpack_s24_32le, pack_s24_32le MAKE_ORC_PACK_UNPACK (s24_32le, s24_32le) #define PACK_S24_32BE GST_AUDIO_FORMAT_S32, unpack_s24_32be, pack_s24_32be MAKE_ORC_PACK_UNPACK (s24_32be, s24_32be) #define PACK_U24_32LE GST_AUDIO_FORMAT_S32, unpack_u24_32le, pack_u24_32le MAKE_ORC_PACK_UNPACK (u24_32le, u24_32le) #define PACK_U24_32BE GST_AUDIO_FORMAT_S32, unpack_u24_32be, pack_u24_32be MAKE_ORC_PACK_UNPACK (u24_32be, u24_32be) #define PACK_S32LE GST_AUDIO_FORMAT_S32, unpack_s32le, pack_s32le MAKE_ORC_PACK_UNPACK (s32le, s32le) #define PACK_S32BE GST_AUDIO_FORMAT_S32, unpack_s32be, pack_s32be MAKE_ORC_PACK_UNPACK (s32be, s32be) #define PACK_U32LE GST_AUDIO_FORMAT_S32, unpack_u32le, pack_u32le MAKE_ORC_PACK_UNPACK (u32le, u32le) #define PACK_U32BE GST_AUDIO_FORMAT_S32, unpack_u32be, pack_u32be MAKE_ORC_PACK_UNPACK (u32be, u32be) #define SIGNED (1U<<31) /* pack from signed integer 32 to integer */ #define WRITE24_TO_LE(p,v) p[0] = v & 0xff; p[1] = (v >> 8) & 0xff; p[2] = (v >> 16) & 0xff #define WRITE24_TO_BE(p,v) p[2] = v & 0xff; p[1] = (v >> 8) & 0xff; p[0] = (v >> 16) & 0xff #define READ24_FROM_LE(p) (p[0] | (p[1] << 8) | (p[2] << 16)) #define READ24_FROM_BE(p) (p[2] | (p[1] << 8) | (p[0] << 16)) #define MAKE_PACK_UNPACK(name, stride, sign, scale, READ_FUNC, WRITE_FUNC) \ static void unpack_ ##name (const GstAudioFormatInfo *info, \ GstAudioPackFlags flags, gpointer dest, \ gconstpointer data, gint length) \ { \ guint32 *d = dest; \ const guint8 *s = data; \ for (;length; length--) { \ *d++ = (((gint32) READ_FUNC (s)) << scale) ^ (sign); \ s += stride; \ } \ } \ static void pack_ ##name (const GstAudioFormatInfo *info, \ GstAudioPackFlags flags, gconstpointer src, \ gpointer data, gint length) \ { \ gint32 tmp; \ const guint32 *s = src; \ guint8 *d = data; \ for (;length; length--) { \ tmp = (*s++ ^ (sign)) >> scale; \ WRITE_FUNC (d, tmp); \ d += stride; \ } \ } #define PACK_S24LE GST_AUDIO_FORMAT_S32, unpack_s24le, pack_s24le MAKE_PACK_UNPACK (s24le, 3, 0, 8, READ24_FROM_LE, WRITE24_TO_LE) #define PACK_U24LE GST_AUDIO_FORMAT_S32, unpack_u24le, pack_u24le MAKE_PACK_UNPACK (u24le, 3, SIGNED, 8, READ24_FROM_LE, WRITE24_TO_LE) #define PACK_S24BE GST_AUDIO_FORMAT_S32, unpack_s24be, pack_s24be MAKE_PACK_UNPACK (s24be, 3, 0, 8, READ24_FROM_BE, WRITE24_TO_BE) #define PACK_U24BE GST_AUDIO_FORMAT_S32, unpack_u24be, pack_u24be MAKE_PACK_UNPACK (u24be, 3, SIGNED, 8, READ24_FROM_BE, WRITE24_TO_BE) #define PACK_S20LE GST_AUDIO_FORMAT_S32, unpack_s20le, pack_s20le MAKE_PACK_UNPACK (s20le, 3, 0, 12, READ24_FROM_LE, WRITE24_TO_LE) #define PACK_U20LE GST_AUDIO_FORMAT_S32, unpack_u20le, pack_u20le MAKE_PACK_UNPACK (u20le, 3, SIGNED, 12, READ24_FROM_LE, WRITE24_TO_LE) #define PACK_S20BE GST_AUDIO_FORMAT_S32, unpack_s20be, pack_s20be MAKE_PACK_UNPACK (s20be, 3, 0, 12, READ24_FROM_BE, WRITE24_TO_BE) #define PACK_U20BE GST_AUDIO_FORMAT_S32, unpack_u20be, pack_u20be MAKE_PACK_UNPACK (u20be, 3, SIGNED, 12, READ24_FROM_BE, WRITE24_TO_BE) #define PACK_S18LE GST_AUDIO_FORMAT_S32, unpack_s18le, pack_s18le MAKE_PACK_UNPACK (s18le, 3, 0, 14, READ24_FROM_LE, WRITE24_TO_LE) #define PACK_U18LE GST_AUDIO_FORMAT_S32, unpack_u18le, pack_u18le MAKE_PACK_UNPACK (u18le, 3, SIGNED, 14, READ24_FROM_LE, WRITE24_TO_LE) #define PACK_S18BE GST_AUDIO_FORMAT_S32, unpack_s18be, pack_s18be MAKE_PACK_UNPACK (s18be, 3, 0, 14, READ24_FROM_BE, WRITE24_TO_BE) #define PACK_U18BE GST_AUDIO_FORMAT_S32, unpack_u18be, pack_u18be MAKE_PACK_UNPACK (u18be, 3, SIGNED, 14, READ24_FROM_BE, WRITE24_TO_BE) #define PACK_F32LE GST_AUDIO_FORMAT_F64, unpack_f32le, pack_f32le MAKE_ORC_PACK_UNPACK (f32le, f32le) #define PACK_F32BE GST_AUDIO_FORMAT_F64, unpack_f32be, pack_f32be MAKE_ORC_PACK_UNPACK (f32be, f32be) #define PACK_F64LE GST_AUDIO_FORMAT_F64, unpack_f64le, pack_f64le MAKE_ORC_PACK_UNPACK (f64le, f64le) #define PACK_F64BE GST_AUDIO_FORMAT_F64, unpack_f64be, pack_f64be MAKE_ORC_PACK_UNPACK (f64be, f64be) #define SINT (GST_AUDIO_FORMAT_FLAG_INTEGER | GST_AUDIO_FORMAT_FLAG_SIGNED) #define SINT_PACK (SINT | GST_AUDIO_FORMAT_FLAG_UNPACK) #define UINT (GST_AUDIO_FORMAT_FLAG_INTEGER) #define FLOAT (GST_AUDIO_FORMAT_FLAG_FLOAT) #define FLOAT_PACK (FLOAT | GST_AUDIO_FORMAT_FLAG_UNPACK) #define MAKE_FORMAT(str,desc,flags,end,width,depth,silent, pack) \ { GST_AUDIO_FORMAT_ ##str, G_STRINGIFY(str), desc, flags, end, width, depth, silent, pack } #define SILENT_0 { 0, 0, 0, 0, 0, 0, 0, 0 } #define SILENT_U8 { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 } #define SILENT_U16LE { 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80 } #define SILENT_U16BE { 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 } #define SILENT_U24_32LE { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00 } #define SILENT_U24_32BE { 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 } #define SILENT_U32LE { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80 } #define SILENT_U32BE { 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 } #define SILENT_U24LE { 0x00, 0x00, 0x80, 0x00, 0x00, 0x80 } #define SILENT_U24BE { 0x80, 0x00, 0x00, 0x80, 0x00, 0x00 } #define SILENT_U20LE { 0x00, 0x00, 0x08, 0x00, 0x00, 0x08 } #define SILENT_U20BE { 0x08, 0x00, 0x00, 0x08, 0x00, 0x00 } #define SILENT_U18LE { 0x00, 0x00, 0x02, 0x00, 0x00, 0x02 } #define SILENT_U18BE { 0x02, 0x00, 0x00, 0x02, 0x00, 0x00 } static const GstAudioFormatInfo formats[] = { {GST_AUDIO_FORMAT_UNKNOWN, "UNKNOWN", "Unknown audio", 0, 0, 0, 0}, {GST_AUDIO_FORMAT_ENCODED, "ENCODED", "Encoded audio", GST_AUDIO_FORMAT_FLAG_COMPLEX, 0, 0, 0}, /* 8 bit */ MAKE_FORMAT (S8, "8-bit signed PCM audio", SINT, 0, 8, 8, SILENT_0, PACK_S8), MAKE_FORMAT (U8, "8-bit unsigned PCM audio", UINT, 0, 8, 8, SILENT_U8, PACK_U8), /* 16 bit */ MAKE_FORMAT (S16LE, "16-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 16, 16, SILENT_0, PACK_S16LE), MAKE_FORMAT (S16BE, "16-bit signed PCM audio", SINT, G_BIG_ENDIAN, 16, 16, SILENT_0, PACK_S16BE), MAKE_FORMAT (U16LE, "16-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 16, 16, SILENT_U16LE, PACK_U16LE), MAKE_FORMAT (U16BE, "16-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 16, 16, SILENT_U16BE, PACK_U16BE), /* 24 bit in low 3 bytes of 32 bits */ MAKE_FORMAT (S24_32LE, "24-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 32, 24, SILENT_0, PACK_S24_32LE), MAKE_FORMAT (S24_32BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32, 24, SILENT_0, PACK_S24_32BE), MAKE_FORMAT (U24_32LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 32, 24, SILENT_U24_32LE, PACK_U24_32LE), MAKE_FORMAT (U24_32BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32, 24, SILENT_U24_32BE, PACK_U24_32BE), /* 32 bit */ #if G_BYTE_ORDER == G_LITTLE_ENDIAN MAKE_FORMAT (S32LE, "32-bit signed PCM audio", SINT_PACK, G_LITTLE_ENDIAN, 32, 32, SILENT_0, PACK_S32LE), MAKE_FORMAT (S32BE, "32-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32, 32, SILENT_0, PACK_S32BE), #else MAKE_FORMAT (S32LE, "32-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 32, 32, SILENT_0, PACK_S32LE), MAKE_FORMAT (S32BE, "32-bit signed PCM audio", SINT_PACK, G_BIG_ENDIAN, 32, 32, SILENT_0, PACK_S32BE), #endif MAKE_FORMAT (U32LE, "32-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 32, 32, SILENT_U32LE, PACK_U32LE), MAKE_FORMAT (U32BE, "32-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32, 32, SILENT_U32BE, PACK_U32BE), /* 24 bit in 3 bytes */ MAKE_FORMAT (S24LE, "24-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 24, SILENT_0, PACK_S24LE), MAKE_FORMAT (S24BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 24, SILENT_0, PACK_S24BE), MAKE_FORMAT (U24LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, 24, SILENT_U24LE, PACK_U24LE), MAKE_FORMAT (U24BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 24, SILENT_U24BE, PACK_U24BE), /* 20 bit in 3 bytes */ MAKE_FORMAT (S20LE, "20-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 20, SILENT_0, PACK_S20LE), MAKE_FORMAT (S20BE, "20-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 20, SILENT_0, PACK_S20BE), MAKE_FORMAT (U20LE, "20-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, 20, SILENT_U20LE, PACK_U20LE), MAKE_FORMAT (U20BE, "20-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 20, SILENT_U20BE, PACK_U20BE), /* 18 bit in 3 bytes */ MAKE_FORMAT (S18LE, "18-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 18, SILENT_0, PACK_S18LE), MAKE_FORMAT (S18BE, "18-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 18, SILENT_0, PACK_S18BE), MAKE_FORMAT (U18LE, "18-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, 18, SILENT_U18LE, PACK_U18LE), MAKE_FORMAT (U18BE, "18-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 18, SILENT_U18BE, PACK_U18BE), /* float */ MAKE_FORMAT (F32LE, "32-bit floating-point audio", GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 32, 32, SILENT_0, PACK_F32LE), MAKE_FORMAT (F32BE, "32-bit floating-point audio", GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 32, 32, SILENT_0, PACK_F32BE), #if G_BYTE_ORDER == G_LITTLE_ENDIAN MAKE_FORMAT (F64LE, "64-bit floating-point audio", FLOAT_PACK, G_LITTLE_ENDIAN, 64, 64, SILENT_0, PACK_F64LE), MAKE_FORMAT (F64BE, "64-bit floating-point audio", FLOAT, G_BIG_ENDIAN, 64, 64, SILENT_0, PACK_F64BE) #else MAKE_FORMAT (F64LE, "64-bit floating-point audio", FLOAT, G_LITTLE_ENDIAN, 64, 64, SILENT_0, PACK_F64LE), MAKE_FORMAT (F64BE, "64-bit floating-point audio", FLOAT_PACK, G_BIG_ENDIAN, 64, 64, SILENT_0, PACK_F64BE) #endif }; G_DEFINE_POINTER_TYPE (GstAudioFormatInfo, gst_audio_format_info); /** * gst_audio_format_build_integer: * @sign: signed or unsigned format * @endianness: G_LITTLE_ENDIAN or G_BIG_ENDIAN * @width: amount of bits used per sample * @depth: amount of used bits in @width * * Construct a #GstAudioFormat with given parameters. * * Returns: a #GstAudioFormat or GST_AUDIO_FORMAT_UNKNOWN when no audio format * exists with the given parameters. */ GstAudioFormat gst_audio_format_build_integer (gboolean sign, gint endianness, gint width, gint depth) { gint i, e; for (i = 0; i < G_N_ELEMENTS (formats); i++) { const GstAudioFormatInfo *finfo = &formats[i]; /* must be int */ if (!GST_AUDIO_FORMAT_INFO_IS_INTEGER (finfo)) continue; /* width and depth must match */ if (width != GST_AUDIO_FORMAT_INFO_WIDTH (finfo)) continue; if (depth != GST_AUDIO_FORMAT_INFO_DEPTH (finfo)) continue; /* if there is endianness, it must match */ e = GST_AUDIO_FORMAT_INFO_ENDIANNESS (finfo); if (e && e != endianness) continue; /* check sign */ if ((sign && !GST_AUDIO_FORMAT_INFO_IS_SIGNED (finfo)) || (!sign && GST_AUDIO_FORMAT_INFO_IS_SIGNED (finfo))) continue; return GST_AUDIO_FORMAT_INFO_FORMAT (finfo); } return GST_AUDIO_FORMAT_UNKNOWN; } /** * gst_audio_format_from_string: * @format: a format string * * Convert the @format string to its #GstAudioFormat. * * Returns: the #GstAudioFormat for @format or GST_AUDIO_FORMAT_UNKNOWN when the * string is not a known format. */ GstAudioFormat gst_audio_format_from_string (const gchar * format) { guint i; g_return_val_if_fail (format != NULL, GST_AUDIO_FORMAT_UNKNOWN); for (i = 0; i < G_N_ELEMENTS (formats); i++) { if (strcmp (GST_AUDIO_FORMAT_INFO_NAME (&formats[i]), format) == 0) return GST_AUDIO_FORMAT_INFO_FORMAT (&formats[i]); } return GST_AUDIO_FORMAT_UNKNOWN; } /** * gst_audio_format_to_string: * @format: a #GstAudioFormat audio format * * Returns a string containing a descriptive name for the #GstAudioFormat. * * Since 1.26 this can also be used with %GST_AUDIO_FORMAT_UNKNOWN, previous * versions were printing a critical warning and returned %NULL. * * Returns: the name corresponding to @format */ const gchar * gst_audio_format_to_string (GstAudioFormat format) { g_return_val_if_fail ((gint) format < G_N_ELEMENTS (formats), NULL); /* In case glib checks are disabled */ if ((gint) format >= G_N_ELEMENTS (formats)) return NULL; return GST_AUDIO_FORMAT_INFO_NAME (&formats[format]); } /** * gst_audio_format_get_info: * @format: a #GstAudioFormat * * Get the #GstAudioFormatInfo for @format * * Returns: The #GstAudioFormatInfo for @format. */ const GstAudioFormatInfo * gst_audio_format_get_info (GstAudioFormat format) { g_return_val_if_fail ((gint) format < G_N_ELEMENTS (formats), NULL); return &formats[format]; } /** * gst_audio_format_fill_silence: * @info: a #GstAudioFormatInfo * @dest: (array length=length) (element-type guint8): a destination * to fill * @length: the length to fill * * Fill @length bytes in @dest with silence samples for @info. * * Deprecated: 1.20: Use gst_audio_format_info_fill_silence() instead. */ void gst_audio_format_fill_silence (const GstAudioFormatInfo * info, gpointer dest, gsize length) { gst_audio_format_info_fill_silence (info, dest, length); } /** * gst_audio_format_info_fill_silence: * @info: a #GstAudioFormatInfo * @dest: (array length=length) (element-type guint8): a destination * to fill * @length: the length to fill * * Fill @length bytes in @dest with silence samples for @info. * * Since: 1.20 */ void gst_audio_format_info_fill_silence (const GstAudioFormatInfo * info, gpointer dest, gsize length) { guint8 *dptr = dest; g_return_if_fail (GST_AUDIO_FORMAT_INFO_IS_VALID_RAW (info)); g_return_if_fail (dest != NULL); if (info->flags & GST_AUDIO_FORMAT_FLAG_FLOAT || info->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) { /* float or signed always 0 */ orc_memset (dest, 0, length); } else { gint i, j, bps = info->width >> 3; switch (bps) { case 1: orc_memset (dest, info->silence[0], length); break; case 2:{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN guint16 silence = GST_READ_UINT16_LE (info->silence); #else guint16 silence = GST_READ_UINT16_BE (info->silence); #endif audio_orc_splat_u16 (dest, silence, length / bps); break; } case 4:{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN guint32 silence = GST_READ_UINT32_LE (info->silence); #else guint32 silence = GST_READ_UINT32_BE (info->silence); #endif audio_orc_splat_u32 (dest, silence, length / bps); break; } case 8:{ #if G_BYTE_ORDER == G_LITTLE_ENDIAN guint64 silence = GST_READ_UINT64_LE (info->silence); #else guint64 silence = GST_READ_UINT64_BE (info->silence); #endif audio_orc_splat_u64 (dest, silence, length / bps); break; } default: for (i = 0; i < length; i += bps) { for (j = 0; j < bps; j++) *dptr++ = info->silence[j]; } break; } } } struct RawAudioFormats { GstAudioFormat *formats; guint n; }; static gpointer generate_raw_audio_formats (gpointer data) { GValue list = G_VALUE_INIT; struct RawAudioFormats *all = g_new (struct RawAudioFormats, 1); gchar *tmp; guint i; gboolean res G_GNUC_UNUSED; g_value_init (&list, GST_TYPE_LIST); /* Workaround a bug in our parser that would lead to segfaults * when deserializing container types using static strings, * see https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/446 */ tmp = g_strdup (GST_AUDIO_FORMATS_ALL); res = gst_value_deserialize (&list, tmp); g_assert (res); g_free (tmp); all->n = gst_value_list_get_size (&list); all->formats = g_new (GstAudioFormat, all->n); for (i = 0; i < all->n; i++) { const GValue *v = gst_value_list_get_value (&list, i); all->formats[i] = gst_audio_format_from_string (g_value_get_string (v)); g_assert (all->formats[i] != GST_AUDIO_FORMAT_UNKNOWN && all->formats[i] != GST_AUDIO_FORMAT_ENCODED); } g_value_unset (&list); return all; } /** * gst_audio_formats_raw: * @len: (out): the number of elements in the returned array * * Return all the raw audio formats supported by GStreamer. * * Returns: (transfer none) (array length=len): an array of #GstAudioFormat * Since: 1.18 */ const GstAudioFormat * gst_audio_formats_raw (guint * len) { static GOnce raw_audio_formats_once = G_ONCE_INIT; struct RawAudioFormats *all; g_return_val_if_fail (len, NULL); g_once (&raw_audio_formats_once, generate_raw_audio_formats, NULL); all = raw_audio_formats_once.retval; *len = all->n; return all->formats; } /** * gst_audio_make_raw_caps: * @formats: (array length=len) (nullable): an array of raw #GstAudioFormat, or %NULL * @len: the size of @formats * @layout: the layout of audio samples * * Return a generic raw audio caps for formats defined in @formats. * If @formats is %NULL returns a caps for all the supported raw audio formats, * see gst_audio_formats_raw(). * * Returns: (transfer full): an audio @GstCaps * Since: 1.18 */ GstCaps * gst_audio_make_raw_caps (const GstAudioFormat formats[], guint len, GstAudioLayout layout) { GstStructure *s; GValue format = G_VALUE_INIT; GstCaps *caps; const gchar *layout_str; g_return_val_if_fail ((formats && len > 0) || (!formats && len == 0), NULL); if (!formats) { formats = gst_audio_formats_raw (&len); } if (len > 1) { guint i; g_value_init (&format, GST_TYPE_LIST); for (i = 0; i < len; i++) { GValue v = G_VALUE_INIT; g_return_val_if_fail (formats[i] != GST_AUDIO_FORMAT_UNKNOWN && formats[i] != GST_AUDIO_FORMAT_ENCODED, NULL); g_value_init (&v, G_TYPE_STRING); g_value_set_static_string (&v, gst_audio_format_to_string (formats[i])); gst_value_list_append_and_take_value (&format, &v); } } else { g_value_init (&format, G_TYPE_STRING); g_value_set_static_string (&format, gst_audio_format_to_string (formats[0])); } if (layout == GST_AUDIO_LAYOUT_INTERLEAVED) layout_str = "interleaved"; else layout_str = "non-interleaved"; s = gst_structure_new_static_str ("audio/x-raw", "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT, "layout", G_TYPE_STRING, layout_str, NULL); gst_structure_take_value_static_str (s, "format", &format); caps = gst_caps_new_full (s, NULL); return caps; }