From 3da0b718768d671a44e4c8a6f994280a5dcc7a18 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 8 Jun 2012 10:10:08 +0200 Subject: [PATCH] audio: split audio header into logical parts --- gst-libs/gst/audio/Makefile.am | 9 + gst-libs/gst/audio/audio-channels.c | 464 ++++++++++++ gst-libs/gst/audio/audio-channels.h | 166 ++++ gst-libs/gst/audio/audio-format.c | 257 +++++++ gst-libs/gst/audio/audio-format.h | 324 ++++++++ gst-libs/gst/audio/audio-info.c | 460 ++++++++++++ gst-libs/gst/audio/audio-info.h | 133 ++++ gst-libs/gst/audio/audio.c | 1085 --------------------------- gst-libs/gst/audio/audio.h | 529 +------------ 9 files changed, 1818 insertions(+), 1609 deletions(-) create mode 100644 gst-libs/gst/audio/audio-channels.c create mode 100644 gst-libs/gst/audio/audio-channels.h create mode 100644 gst-libs/gst/audio/audio-format.c create mode 100644 gst-libs/gst/audio/audio-format.h create mode 100644 gst-libs/gst/audio/audio-info.c create mode 100644 gst-libs/gst/audio/audio-info.h diff --git a/gst-libs/gst/audio/Makefile.am b/gst-libs/gst/audio/Makefile.am index 64a8db7f61..0c0556122a 100644 --- a/gst-libs/gst/audio/Makefile.am +++ b/gst-libs/gst/audio/Makefile.am @@ -1,6 +1,9 @@ # variables used for enum/marshal generation glib_enum_headers= \ audio.h \ + audio-format.h \ + audio-channels.h \ + audio-info.h \ gstaudioringbuffer.h glib_enum_define = GST_AUDIO @@ -20,6 +23,9 @@ CLEANFILES = $(BUILT_SOURCES) libgstaudio_@GST_API_VERSION@_la_SOURCES = \ audio.c \ + audio-format.c \ + audio-channels.c \ + audio-info.c \ gstaudioringbuffer.c \ gstaudioclock.c \ gstaudiocdsrc.c \ @@ -39,6 +45,9 @@ nodist_libgstaudio_@GST_API_VERSION@_la_SOURCES = $(built_sources) $(built_heade libgstaudio_@GST_API_VERSION@includedir = $(includedir)/gstreamer-@GST_API_VERSION@/gst/audio libgstaudio_@GST_API_VERSION@include_HEADERS = \ audio.h \ + audio-format.h \ + audio-channels.h \ + audio-info.h \ gstaudioringbuffer.h \ gstaudioclock.h \ gstaudiofilter.h \ diff --git a/gst-libs/gst/audio/audio-channels.c b/gst-libs/gst/audio/audio-channels.c new file mode 100644 index 0000000000..660fbe241e --- /dev/null +++ b/gst-libs/gst/audio/audio-channels.c @@ -0,0 +1,464 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:gstaudio + * @short_description: Support library for audio elements + * + * This library contains some helper functions for audio elements. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "audio-channels.h" + +static const GstAudioChannelPosition default_channel_order[64] = { + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE1, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE2, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, + GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT, + GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID, + GST_AUDIO_CHANNEL_POSITION_INVALID +}; + +static gboolean +check_valid_channel_positions (const GstAudioChannelPosition * position, + gint channels, gboolean enforce_order, guint64 * channel_mask_out) +{ + gint i, j; + guint64 channel_mask = 0; + + if (channels == 1 && position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) { + if (channel_mask_out) + *channel_mask_out = 0; + return TRUE; + } + + if (channels > 0 && position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { + if (channel_mask_out) + *channel_mask_out = 0; + return TRUE; + } + + j = 0; + for (i = 0; i < channels; i++) { + while (j < G_N_ELEMENTS (default_channel_order) + && default_channel_order[j] != position[i]) + j++; + + if (position[i] == GST_AUDIO_CHANNEL_POSITION_INVALID || + position[i] == GST_AUDIO_CHANNEL_POSITION_MONO || + position[i] == GST_AUDIO_CHANNEL_POSITION_NONE) + return FALSE; + + /* Is this in valid channel order? */ + if (enforce_order && j == G_N_ELEMENTS (default_channel_order)) + return FALSE; + j++; + + if ((channel_mask & (G_GUINT64_CONSTANT (1) << position[i]))) + return FALSE; + + channel_mask |= (G_GUINT64_CONSTANT (1) << position[i]); + } + + if (channel_mask_out) + *channel_mask_out = channel_mask; + + return TRUE; +} + +/** + * gst_audio_reorder_channels: + * @data: The pointer to the memory. + * @size: The size of the memory. + * @format: The %GstAudioFormat of the buffer. + * @channels: The number of channels. + * @from: The channel positions in the buffer. + * @to: The channel positions to convert to. + * + * Reorders @data from the channel positions @from to the channel + * positions @to. @from and @to must contain the same number of + * positions and the same positions, only in a different order. + * + * Returns: %TRUE if the reordering was possible. + */ +gboolean +gst_audio_reorder_channels (gpointer data, gsize size, GstAudioFormat format, + gint channels, const GstAudioChannelPosition * from, + const GstAudioChannelPosition * to) +{ + const GstAudioFormatInfo *info; + gint i, j, n; + gint reorder_map[64] = { 0, }; + guint8 *ptr; + gint bpf, bps; + guint8 tmp[64 * 8]; + + info = gst_audio_format_get_info (format); + + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (from != NULL, FALSE); + g_return_val_if_fail (to != NULL, FALSE); + g_return_val_if_fail (info != NULL && info->width > 0, FALSE); + g_return_val_if_fail (info->width > 0, FALSE); + g_return_val_if_fail (info->width <= 8 * 64, FALSE); + g_return_val_if_fail (size % ((info->width * channels) / 8) == 0, FALSE); + g_return_val_if_fail (channels > 0, FALSE); + g_return_val_if_fail (channels <= 64, FALSE); + + if (size == 0) + return TRUE; + + if (memcmp (from, to, channels * sizeof (from[0])) == 0) + return TRUE; + + if (!gst_audio_get_channel_reorder_map (channels, from, to, reorder_map)) + return FALSE; + + bps = info->width / 8; + bpf = bps * channels; + ptr = data; + + n = size / bpf; + for (i = 0; i < n; i++) { + + memcpy (tmp, ptr, bpf); + for (j = 0; j < channels; j++) + memcpy (ptr + reorder_map[j] * bps, tmp + j * bps, bps); + + ptr += bpf; + } + + return TRUE; +} + +/** + * gst_audio_buffer_reorder_channels: + * @buffer: The buffer to reorder. + * @format: The %GstAudioFormat of the buffer. + * @channels: The number of channels. + * @from: The channel positions in the buffer. + * @to: The channel positions to convert to. + * + * Reorders @buffer from the channel positions @from to the channel + * positions @to. @from and @to must contain the same number of + * positions and the same positions, only in a different order. + * @buffer must be writable. + * + * Returns: %TRUE if the reordering was possible. + */ +gboolean +gst_audio_buffer_reorder_channels (GstBuffer * buffer, + GstAudioFormat format, gint channels, + const GstAudioChannelPosition * from, const GstAudioChannelPosition * to) +{ + GstMapInfo info; + gboolean ret; + + g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); + g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); + + gst_buffer_map (buffer, &info, GST_MAP_READWRITE); + + ret = + gst_audio_reorder_channels (info.data, info.size, format, channels, from, + to); + + gst_buffer_unmap (buffer, &info); + + return ret; +} + +/** + * gst_audio_check_valid_channel_positions: + * @position: The %GstAudioChannelPositions to check. + * @channels: The number of channels. + * @force_order: Only consider the GStreamer channel order. + * + * Checks if @position contains valid channel positions for + * @channels channels. If @force_order is %TRUE it additionally + * checks if the channels are in the order required by GStreamer. + * + * Returns: %TRUE if the channel positions are valid. + */ +gboolean +gst_audio_check_valid_channel_positions (const GstAudioChannelPosition * + position, gint channels, gboolean force_order) +{ + return check_valid_channel_positions (position, channels, force_order, NULL); +} + +/** + * gst_audio_channel_positions_to_mask: + * @position: The %GstAudioChannelPositions + * @channels: The number of channels. + * @force_order: Only consider the GStreamer channel order. + * @channel_mask: the output channel mask + * + * Convert the @position array of @channels channels to a bitmask. + * + * If @force_order is %TRUE it additionally checks if the channels are + * in the order required by GStreamer. + * + * Returns: %TRUE if the channel positions are valid and could be converted. + */ +gboolean +gst_audio_channel_positions_to_mask (const GstAudioChannelPosition * position, + gint channels, gboolean force_order, guint64 * channel_mask) +{ + return check_valid_channel_positions (position, channels, force_order, + channel_mask); +} + +/** + * gst_audio_channel_positions_from_mask: + * @channels: The number of channels + * @channel_mask: The input channel_mask + * @position: The %GstAudioChannelPositions + * @caps: a #GstCaps + * + * Convert the @channels present in @channel_mask to a @position array + * (which should have at least @channels entries ensured by caller). + * If @channel_mask is set to 0, it is considered as 'not present' for purpose + * of conversion. + * + * Returns: %TRUE if channel and channel mask are valid and could be converted + */ +gboolean +gst_audio_channel_positions_from_mask (gint channels, guint64 channel_mask, + GstAudioChannelPosition * position) +{ + g_return_val_if_fail (position != NULL, FALSE); + g_return_val_if_fail (channels != 0, FALSE); + + GST_DEBUG ("converting %d channels for " + " channel mask 0x%016" G_GINT64_MODIFIER "x", channels, channel_mask); + + if (!channel_mask) { + if (channels == 1) { + position[0] = GST_AUDIO_CHANNEL_POSITION_MONO; + } else if (channels == 2) { + position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; + position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; + } else { + goto no_channel_mask; + } + } else { + gint i, j; + + j = 0; + for (i = 0; i < 64; i++) { + if ((channel_mask & (G_GUINT64_CONSTANT (1) << i))) { + if (j < channels) + position[j] = default_channel_order[i]; + if (default_channel_order[i] == GST_AUDIO_CHANNEL_POSITION_INVALID) + goto invalid_channel_mask; + j++; + } + } + + if (j != channels) + goto invalid_channel_mask; + } + + return TRUE; + + /* ERROR */ +no_channel_mask: + { + GST_ERROR ("no channel-mask property given"); + return FALSE; + } +invalid_channel_mask: + { + GST_ERROR ("Invalid channel mask 0x%016" G_GINT64_MODIFIER + "x for %d channels", channel_mask, channels); + return FALSE; + } +} + + +/** + * gst_audio_get_channel_reorder_map: + * @channels: The number of channels. + * @from: The channel positions to reorder from. + * @to: The channel positions to reorder to. + * @reorder_map: Pointer to the reorder map. + * + * Returns a reorder map for @from to @to that can be used in + * custom channel reordering code, e.g. to convert from or to the + * GStreamer channel order. @from and @to must contain the same + * number of positions and the same positions, only in a + * different order. + * + * The resulting @reorder_map can be used for reordering by assigning + * channel i of the input to channel reorder_map[i] of the output. + * + * Returns: %TRUE if the channel positions are valid and reordering + * is possible. + */ +gboolean +gst_audio_get_channel_reorder_map (gint channels, + const GstAudioChannelPosition * from, const GstAudioChannelPosition * to, + gint * reorder_map) +{ + gint i, j; + + g_return_val_if_fail (reorder_map != NULL, FALSE); + g_return_val_if_fail (channels > 0, FALSE); + g_return_val_if_fail (from != NULL, FALSE); + g_return_val_if_fail (to != NULL, FALSE); + g_return_val_if_fail (check_valid_channel_positions (from, channels, FALSE, + NULL), FALSE); + g_return_val_if_fail (check_valid_channel_positions (to, channels, FALSE, + NULL), FALSE); + + /* Build reorder map and check compatibility */ + for (i = 0; i < channels; i++) { + if (from[i] == GST_AUDIO_CHANNEL_POSITION_NONE + || to[i] == GST_AUDIO_CHANNEL_POSITION_NONE) + return FALSE; + if (from[i] == GST_AUDIO_CHANNEL_POSITION_INVALID + || to[i] == GST_AUDIO_CHANNEL_POSITION_INVALID) + return FALSE; + if (from[i] == GST_AUDIO_CHANNEL_POSITION_MONO + || to[i] == GST_AUDIO_CHANNEL_POSITION_MONO) + return FALSE; + + for (j = 0; j < channels; j++) { + if (from[i] == to[j]) { + reorder_map[i] = j; + break; + } + } + + /* Not all channels present in both */ + if (j == channels) + return FALSE; + } + + return TRUE; +} + +/** + * gst_audio_channel_positions_to_valid_order: + * @position: The channel positions to reorder to. + * @channels: The number of channels. + * + * Reorders the channel positions in @position from any order to + * the GStreamer channel order. + * + * Returns: %TRUE if the channel positions are valid and reordering + * was successful. + */ +gboolean +gst_audio_channel_positions_to_valid_order (GstAudioChannelPosition * position, + gint channels) +{ + GstAudioChannelPosition tmp[64]; + guint64 channel_mask = 0; + gint i, j; + + g_return_val_if_fail (channels > 0, FALSE); + g_return_val_if_fail (position != NULL, FALSE); + g_return_val_if_fail (check_valid_channel_positions (position, channels, + FALSE, NULL), FALSE); + + if (channels == 1 && position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) + return TRUE; + if (position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) + return TRUE; + + check_valid_channel_positions (position, channels, FALSE, &channel_mask); + + memset (tmp, 0xff, sizeof (tmp)); + j = 0; + for (i = 0; i < 64; i++) { + if ((channel_mask & (G_GUINT64_CONSTANT (1) << i))) { + tmp[j] = i; + j++; + } + } + + memcpy (position, tmp, sizeof (tmp[0]) * channels); + + return TRUE; +} diff --git a/gst-libs/gst/audio/audio-channels.h b/gst-libs/gst/audio/audio-channels.h new file mode 100644 index 0000000000..7885140db5 --- /dev/null +++ b/gst-libs/gst/audio/audio-channels.h @@ -0,0 +1,166 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2001> Thomas Vander Stichele + * <2011> 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_CHANNELS_H__ +#define __GST_AUDIO_CHANNELS_H__ + +#include + +#include + +G_BEGIN_DECLS + +/** + * GstAudioChannelPosition: + * @GST_AUDIO_CHANNEL_POSITION_MONO: Mono without direction; + * can only be used with 1 channel + * @GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: Front left + * @GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: Front right + * @GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: Front center + * @GST_AUDIO_CHANNEL_POSITION_LFE1: Low-frequency effects 1 (subwoofer) + * @GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: Rear left + * @GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: Rear right + * @GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: Front left of center + * @GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: Front right of center + * @GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: Rear center + * @GST_AUDIO_CHANNEL_POSITION_LFE2: Low-frequency effects 2 (subwoofer) + * @GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: Side left + * @GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: Side right + * @GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT: Top front left + * @GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT: Top front right + * @GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER: Top front center + * @GST_AUDIO_CHANNEL_POSITION_TOP_CENTER: Top center + * @GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT: Top rear left + * @GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT: Top rear right + * @GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT: Top side right + * @GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT: Top rear right + * @GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER: Top rear center + * @GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER: Bottom front center + * @GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT: Bottom front left + * @GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT: Bottom front right + * @GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT: Wide left (between front left and side left) + * @GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT: Wide right (between front right and side right) + * @GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT: Surround left (between rear left and side left) + * @GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT: Surround right (between rear right and side right) + * @GST_AUDIO_CHANNEL_POSITION_NONE: used for position-less channels, e.g. + * from a sound card that records 1024 channels; mutually exclusive with + * any other channel position + * @GST_AUDIO_CHANNEL_POSITION_INVALID: invalid position + * + * Audio channel positions. + * + * These are the channels defined in SMPTE 2036-2-2008 + * Table 1 for 22.2 audio systems with the Surround and Wide channels from + * DTS Coherent Acoustics (v.1.3.1) and 10.2 and 7.1 layouts. In the caps the + * actual channel layout is expressed with a channel count and a channel mask, + * which describes the existing channels. The positions in the bit mask correspond + * to the enum values. + * For negotiation it is allowed to have more bits set in the channel mask than + * the number of channels to specify the allowed channel positions but this is + * not allowed in negotiated caps. It is not allowed in any situation other + * than the one mentioned below to have less bits set in the channel mask than + * the number of channels. + * + * @GST_AUDIO_CHANNEL_POSITION_MONO can only be used with a single mono channel that + * has no direction information and would be mixed into all directional channels. + * This is expressed in caps by having a single channel and no channel mask. + * + * @GST_AUDIO_CHANNEL_POSITION_NONE can only be used if all channels have this position. + * This is expressed in caps by having a channel mask with no bits set. + * + * As another special case it is allowed to have two channels without a channel mask. + * This implicitely means that this is a stereo stream with a front left and front right + * channel. + */ +typedef enum { + /* These get negative indices to allow to use + * the enum values of the normal cases for the + * bit-mask position */ + GST_AUDIO_CHANNEL_POSITION_NONE = -3, + GST_AUDIO_CHANNEL_POSITION_MONO = -2, + GST_AUDIO_CHANNEL_POSITION_INVALID = -1, + + /* Normal cases */ + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT = 0, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE1, + GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_LFE2, + GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, + GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, + GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER, + GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER, + GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT, + GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT, + GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT, + GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT, + GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT, + GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT +} GstAudioChannelPosition; + +#define GST_AUDIO_CHANNEL_POSITION_MASK(pos) (G_GUINT64_CONSTANT(1)<< GST_AUDIO_CHANNEL_POSITION_ ## pos) + +gboolean gst_audio_buffer_reorder_channels (GstBuffer * buffer, + GstAudioFormat format, + gint channels, + const GstAudioChannelPosition * from, + const GstAudioChannelPosition * to); + +gboolean gst_audio_reorder_channels (gpointer data, gsize size, + GstAudioFormat format, + gint channels, + const GstAudioChannelPosition * from, + const GstAudioChannelPosition * to); + +gboolean gst_audio_channel_positions_to_valid_order (GstAudioChannelPosition *position, + gint channels); + +gboolean gst_audio_check_valid_channel_positions (const GstAudioChannelPosition *position, + gint channels, gboolean force_order); + +gboolean gst_audio_channel_positions_to_mask (const GstAudioChannelPosition *position, + gint channels, gboolean force_order, + guint64 *channel_mask); + +gboolean gst_audio_channel_positions_from_mask (gint channels, guint64 channel_mask, + GstAudioChannelPosition * position); + +gboolean gst_audio_get_channel_reorder_map (gint channels, + const GstAudioChannelPosition * from, + const GstAudioChannelPosition * to, + gint *reorder_map); + +G_END_DECLS + +#endif /* __GST_AUDIO_CHANNELS_H__ */ diff --git a/gst-libs/gst/audio/audio-format.c b/gst-libs/gst/audio/audio-format.c new file mode 100644 index 0000000000..d6ba4f6dff --- /dev/null +++ b/gst-libs/gst/audio/audio-format.c @@ -0,0 +1,257 @@ +/* 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "audio-format.h" + +#define SINT (GST_AUDIO_FORMAT_FLAG_INTEGER | GST_AUDIO_FORMAT_FLAG_SIGNED) +#define UINT (GST_AUDIO_FORMAT_FLAG_INTEGER) + +#define MAKE_FORMAT(str,desc,flags,end,width,depth,silent) \ + { GST_AUDIO_FORMAT_ ##str, G_STRINGIFY(str), desc, flags, end, width, depth, silent } + +#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 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), + MAKE_FORMAT (U8, "8-bit unsigned PCM audio", UINT, 0, 8, 8, SILENT_U8), + /* 16 bit */ + MAKE_FORMAT (S16LE, "16-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 16, 16, + SILENT_0), + MAKE_FORMAT (S16BE, "16-bit signed PCM audio", SINT, G_BIG_ENDIAN, 16, 16, + SILENT_0), + MAKE_FORMAT (U16LE, "16-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 16, + 16, SILENT_U16LE), + MAKE_FORMAT (U16BE, "16-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 16, 16, + SILENT_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), + MAKE_FORMAT (S24_32BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32, 24, + SILENT_0), + MAKE_FORMAT (U24_32LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 32, + 24, SILENT_U24_32LE), + MAKE_FORMAT (U24_32BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32, + 24, SILENT_U24_32BE), + /* 32 bit */ + MAKE_FORMAT (S32LE, "32-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 32, 32, + SILENT_0), + MAKE_FORMAT (S32BE, "32-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32, 32, + SILENT_0), + MAKE_FORMAT (U32LE, "32-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 32, + 32, SILENT_U32LE), + MAKE_FORMAT (U32BE, "32-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32, 32, + SILENT_U32BE), + /* 24 bit in 3 bytes */ + MAKE_FORMAT (S24LE, "24-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 24, + SILENT_0), + MAKE_FORMAT (S24BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 24, + SILENT_0), + MAKE_FORMAT (U24LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, + 24, SILENT_U24LE), + MAKE_FORMAT (U24BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 24, + SILENT_U24BE), + /* 20 bit in 3 bytes */ + MAKE_FORMAT (S20LE, "20-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 20, + SILENT_0), + MAKE_FORMAT (S20BE, "20-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 20, + SILENT_0), + MAKE_FORMAT (U20LE, "20-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, + 20, SILENT_U20LE), + MAKE_FORMAT (U20BE, "20-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 20, + SILENT_U20BE), + /* 18 bit in 3 bytes */ + MAKE_FORMAT (S18LE, "18-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 18, + SILENT_0), + MAKE_FORMAT (S18BE, "18-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 18, + SILENT_0), + MAKE_FORMAT (U18LE, "18-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, + 18, SILENT_U18LE), + MAKE_FORMAT (U18BE, "18-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 18, + SILENT_U18BE), + /* float */ + MAKE_FORMAT (F32LE, "32-bit floating-point audio", + GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 32, 32, + SILENT_0), + MAKE_FORMAT (F32BE, "32-bit floating-point audio", + GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 32, 32, + SILENT_0), + MAKE_FORMAT (F64LE, "64-bit floating-point audio", + GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 64, 64, + SILENT_0), + MAKE_FORMAT (F64BE, "64-bit floating-point audio", + GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 64, 64, + SILENT_0) +}; + +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++) { + 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; + + 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; +} + +const gchar * +gst_audio_format_to_string (GstAudioFormat format) +{ + g_return_val_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN, NULL); + + if (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 (format < G_N_ELEMENTS (formats), NULL); + + return &formats[format]; +} + +/** + * gst_audio_format_fill_silence: + * @info: a #GstAudioFormatInfo + * @dest: a destination to fill + * @length: the length to fill + * + * Fill @length bytes in @dest with silence samples for @info. + */ +void +gst_audio_format_fill_silence (const GstAudioFormatInfo * info, + gpointer dest, gsize length) +{ + guint8 *dptr = dest; + + g_return_if_fail (info != NULL); + 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 */ + memset (dest, 0, length); + } else { + gint i, j, bps = info->width >> 3; + + switch (bps) { + case 1: + memset (dest, info->silence[0], length); + break; + default: + for (i = 0; i < length; i += bps) { + for (j = 0; j < bps; j++) + *dptr++ = info->silence[j]; + } + break; + } + } +} diff --git a/gst-libs/gst/audio/audio-format.h b/gst-libs/gst/audio/audio-format.h new file mode 100644 index 0000000000..1228e92bb6 --- /dev/null +++ b/gst-libs/gst/audio/audio-format.h @@ -0,0 +1,324 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2001> Thomas Vander Stichele + * <2011> 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#ifndef __GST_AUDIO_FORMAT_H__ +#define __GST_AUDIO_FORMAT_H__ + +G_BEGIN_DECLS + +#include + +#if G_BYTE_ORDER == G_BIG_ENDIAN +#define _GST_AUDIO_FORMAT_NE(fmt) GST_AUDIO_FORMAT_ ## fmt ## BE +#elif G_BYTE_ORDER == G_LITTLE_ENDIAN +#define _GST_AUDIO_FORMAT_NE(fmt) GST_AUDIO_FORMAT_ ## fmt ## LE +#endif + +/** + * GstAudioFormat: + * @GST_AUDIO_FORMAT_UNKNOWN: unknown or unset audio format + * @GST_AUDIO_FORMAT_ENCODED: encoded audio format + * @GST_AUDIO_FORMAT_S8: 8 bits in 8 bits, signed + * @GST_AUDIO_FORMAT_U8: 8 bits in 8 bits, unsigned + * @GST_AUDIO_FORMAT_S16LE: 16 bits in 16 bits, signed, little endian + * @GST_AUDIO_FORMAT_S16BE: 16 bits in 16 bits, signed, big endian + * @GST_AUDIO_FORMAT_U16LE: 16 bits in 16 bits, unsigned, little endian + * @GST_AUDIO_FORMAT_U16BE: 16 bits in 16 bits, unsigned, big endian + * @GST_AUDIO_FORMAT_S24_32LE: 24 bits in 32 bits, signed, little endian + * @GST_AUDIO_FORMAT_S24_32BE: 24 bits in 32 bits, signed, big endian + * @GST_AUDIO_FORMAT_U24_32LE: 24 bits in 32 bits, unsigned, little endian + * @GST_AUDIO_FORMAT_U24_32BE: 24 bits in 32 bits, unsigned, big endian + * @GST_AUDIO_FORMAT_S32LE: 32 bits in 32 bits, signed, little endian + * @GST_AUDIO_FORMAT_S32BE: 32 bits in 32 bits, signed, big endian + * @GST_AUDIO_FORMAT_U32LE: 32 bits in 32 bits, unsigned, little endian + * @GST_AUDIO_FORMAT_U32BE: 32 bits in 32 bits, unsigned, big endian + * @GST_AUDIO_FORMAT_S24LE: 24 bits in 24 bits, signed, little endian + * @GST_AUDIO_FORMAT_S24BE: 24 bits in 24 bits, signed, big endian + * @GST_AUDIO_FORMAT_U24LE: 24 bits in 24 bits, unsigned, little endian + * @GST_AUDIO_FORMAT_U24BE: 24 bits in 24 bits, unsigned, big endian + * @GST_AUDIO_FORMAT_S20LE: 20 bits in 24 bits, signed, little endian + * @GST_AUDIO_FORMAT_S20BE: 20 bits in 24 bits, signed, big endian + * @GST_AUDIO_FORMAT_U20LE: 20 bits in 24 bits, unsigned, little endian + * @GST_AUDIO_FORMAT_U20BE: 20 bits in 24 bits, unsigned, big endian + * @GST_AUDIO_FORMAT_S18LE: 18 bits in 24 bits, signed, little endian + * @GST_AUDIO_FORMAT_S18BE: 18 bits in 24 bits, signed, big endian + * @GST_AUDIO_FORMAT_U18LE: 18 bits in 24 bits, unsigned, little endian + * @GST_AUDIO_FORMAT_U18BE: 18 bits in 24 bits, unsigned, big endian + * @GST_AUDIO_FORMAT_F32LE: 32-bit floating point samples, little endian + * @GST_AUDIO_FORMAT_F32BE: 32-bit floating point samples, big endian + * @GST_AUDIO_FORMAT_F64LE: 64-bit floating point samples, little endian + * @GST_AUDIO_FORMAT_F64BE: 64-bit floating point samples, big endian + * @GST_AUDIO_FORMAT_S16: 16 bits in 16 bits, signed, native endianness + * @GST_AUDIO_FORMAT_U16: 16 bits in 16 bits, unsigned, native endianness + * @GST_AUDIO_FORMAT_S24_32: 24 bits in 32 bits, signed, native endianness + * @GST_AUDIO_FORMAT_U24_32: 24 bits in 32 bits, unsigned, native endianness + * @GST_AUDIO_FORMAT_S32: 32 bits in 32 bits, signed, native endianness + * @GST_AUDIO_FORMAT_U32: 32 bits in 32 bits, unsigned, native endianness + * @GST_AUDIO_FORMAT_S24: 24 bits in 24 bits, signed, native endianness + * @GST_AUDIO_FORMAT_U24: 24 bits in 24 bits, unsigned, native endianness + * @GST_AUDIO_FORMAT_S20: 20 bits in 24 bits, signed, native endianness + * @GST_AUDIO_FORMAT_U20: 20 bits in 24 bits, unsigned, native endianness + * @GST_AUDIO_FORMAT_S18: 18 bits in 24 bits, signed, native endianness + * @GST_AUDIO_FORMAT_U18: 18 bits in 24 bits, unsigned, native endianness + * @GST_AUDIO_FORMAT_F32: 32-bit floating point samples, native endianness + * @GST_AUDIO_FORMAT_F64: 64-bit floating point samples, native endianness + * + * Enum value describing the most common audio formats. + */ +typedef enum { + GST_AUDIO_FORMAT_UNKNOWN, + GST_AUDIO_FORMAT_ENCODED, + /* 8 bit */ + GST_AUDIO_FORMAT_S8, + GST_AUDIO_FORMAT_U8, + /* 16 bit */ + GST_AUDIO_FORMAT_S16LE, + GST_AUDIO_FORMAT_S16BE, + GST_AUDIO_FORMAT_U16LE, + GST_AUDIO_FORMAT_U16BE, + /* 24 bit in low 3 bytes of 32 bits*/ + GST_AUDIO_FORMAT_S24_32LE, + GST_AUDIO_FORMAT_S24_32BE, + GST_AUDIO_FORMAT_U24_32LE, + GST_AUDIO_FORMAT_U24_32BE, + /* 32 bit */ + GST_AUDIO_FORMAT_S32LE, + GST_AUDIO_FORMAT_S32BE, + GST_AUDIO_FORMAT_U32LE, + GST_AUDIO_FORMAT_U32BE, + /* 24 bit in 3 bytes*/ + GST_AUDIO_FORMAT_S24LE, + GST_AUDIO_FORMAT_S24BE, + GST_AUDIO_FORMAT_U24LE, + GST_AUDIO_FORMAT_U24BE, + /* 20 bit in 3 bytes*/ + GST_AUDIO_FORMAT_S20LE, + GST_AUDIO_FORMAT_S20BE, + GST_AUDIO_FORMAT_U20LE, + GST_AUDIO_FORMAT_U20BE, + /* 18 bit in 3 bytes*/ + GST_AUDIO_FORMAT_S18LE, + GST_AUDIO_FORMAT_S18BE, + GST_AUDIO_FORMAT_U18LE, + GST_AUDIO_FORMAT_U18BE, + /* float */ + GST_AUDIO_FORMAT_F32LE, + GST_AUDIO_FORMAT_F32BE, + GST_AUDIO_FORMAT_F64LE, + GST_AUDIO_FORMAT_F64BE, + /* native endianness equivalents */ + GST_AUDIO_FORMAT_S16 = _GST_AUDIO_FORMAT_NE(S16), + GST_AUDIO_FORMAT_U16 = _GST_AUDIO_FORMAT_NE(U16), + GST_AUDIO_FORMAT_S24_32 = _GST_AUDIO_FORMAT_NE(S24_32), + GST_AUDIO_FORMAT_U24_32 = _GST_AUDIO_FORMAT_NE(U24_32), + GST_AUDIO_FORMAT_S32 = _GST_AUDIO_FORMAT_NE(S32), + GST_AUDIO_FORMAT_U32 = _GST_AUDIO_FORMAT_NE(U32), + GST_AUDIO_FORMAT_S24 = _GST_AUDIO_FORMAT_NE(S24), + GST_AUDIO_FORMAT_U24 = _GST_AUDIO_FORMAT_NE(U24), + GST_AUDIO_FORMAT_S20 = _GST_AUDIO_FORMAT_NE(S20), + GST_AUDIO_FORMAT_U20 = _GST_AUDIO_FORMAT_NE(U20), + GST_AUDIO_FORMAT_S18 = _GST_AUDIO_FORMAT_NE(S18), + GST_AUDIO_FORMAT_U18 = _GST_AUDIO_FORMAT_NE(U18), + GST_AUDIO_FORMAT_F32 = _GST_AUDIO_FORMAT_NE(F32), + GST_AUDIO_FORMAT_F64 = _GST_AUDIO_FORMAT_NE(F64) +} GstAudioFormat; + + +typedef struct _GstAudioFormatInfo GstAudioFormatInfo; + +/** + * GstAudioFormatFlags: + * @GST_AUDIO_FORMAT_FLAG_INTEGER: integer samples + * @GST_AUDIO_FORMAT_FLAG_FLOAT: float samples + * @GST_AUDIO_FORMAT_FLAG_SIGNED: signed samples + * @GST_AUDIO_FORMAT_FLAG_COMPLEX: complex layout + * + * The different audio flags that a format info can have. + */ +typedef enum +{ + GST_AUDIO_FORMAT_FLAG_INTEGER = (1 << 0), + GST_AUDIO_FORMAT_FLAG_FLOAT = (1 << 1), + GST_AUDIO_FORMAT_FLAG_SIGNED = (1 << 2), + GST_AUDIO_FORMAT_FLAG_COMPLEX = (1 << 4) +} GstAudioFormatFlags; + +/** + * GstAudioPackFlags: + * @GST_AUDIO_PACK_FLAG_NONE: No flag + * + * The different flags that can be used when packing and unpacking. + */ +typedef enum +{ + GST_AUDIO_PACK_FLAG_NONE = 0 +} GstAudioPackFlags; + +/** + * GstAudioFormatUnpack: + * @info: a #GstAudioFormatInfo + * @dest: a destination array + * @data: pointer to the audio data + * @length: the amount of samples to unpack. + * + * Unpacks @length samples from the given data of format @info. + * The samples will be unpacked into @dest which each channel + * interleaved. @dest should at least be big enough to hold @length * + * channels * size(unpack_format) bytes. + */ +typedef void (*GstAudioFormatUnpack) (const GstAudioFormatInfo *info, + GstAudioPackFlags flags, gpointer dest, + const gpointer data, gint length); +/** + * GstAudioFormatPack: + * @info: a #GstAudioFormatInfo + * @src: a source array + * @data: pointer to the destination data + * @length: the amount of samples to pack. + * + * Packs @length samples from @src to the data array in format @info. + * The samples from source have each channel interleaved + * and will be packed into @data. + */ +typedef void (*GstAudioFormatPack) (const GstAudioFormatInfo *info, + GstAudioPackFlags flags, const gpointer src, + gpointer data, gint length); + +/** + * GstAudioFormatInfo: + * @format: #GstAudioFormat + * @name: string representation of the format + * @description: user readable description of the format + * @flags: #GstAudioFormatFlags + * @endianness: the endianness + * @width: amount of bits used for one sample + * @depth: amount of valid bits in @width + * @silence: @width/8 bytes with 1 silent sample + * @unpack_format: the format of the unpacked samples + * @unpack_func: function to unpack samples + * @pack_func: function to pack samples + * + * Information for an audio format. + */ +struct _GstAudioFormatInfo { + GstAudioFormat format; + const gchar *name; + const gchar *description; + GstAudioFormatFlags flags; + gint endianness; + gint width; + gint depth; + guint8 silence[8]; + + GstAudioFormat unpack_format; + GstAudioFormatUnpack unpack_func; + GstAudioFormatPack pack_func; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_audio_format_info_get_type (void); + +#define GST_AUDIO_FORMAT_INFO_FORMAT(info) ((info)->format) +#define GST_AUDIO_FORMAT_INFO_NAME(info) ((info)->name) +#define GST_AUDIO_FORMAT_INFO_FLAGS(info) ((info)->flags) + +#define GST_AUDIO_FORMAT_INFO_IS_INTEGER(info) !!((info)->flags & GST_AUDIO_FORMAT_FLAG_INTEGER) +#define GST_AUDIO_FORMAT_INFO_IS_FLOAT(info) !!((info)->flags & GST_AUDIO_FORMAT_FLAG_FLOAT) +#define GST_AUDIO_FORMAT_INFO_IS_SIGNED(info) !!((info)->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) + +#define GST_AUDIO_FORMAT_INFO_ENDIANNESS(info) ((info)->endianness) +#define GST_AUDIO_FORMAT_INFO_IS_LITTLE_ENDIAN(info) ((info)->endianness == G_LITTLE_ENDIAN) +#define GST_AUDIO_FORMAT_INFO_IS_BIG_ENDIAN(info) ((info)->endianness == G_BIG_ENDIAN) +#define GST_AUDIO_FORMAT_INFO_WIDTH(info) ((info)->width) +#define GST_AUDIO_FORMAT_INFO_DEPTH(info) ((info)->depth) + + +GstAudioFormat gst_audio_format_build_integer (gboolean sign, gint endianness, + gint width, gint depth) G_GNUC_CONST; + +GstAudioFormat gst_audio_format_from_string (const gchar *format) G_GNUC_CONST; +const gchar * gst_audio_format_to_string (GstAudioFormat format) G_GNUC_CONST; + +const GstAudioFormatInfo * + gst_audio_format_get_info (GstAudioFormat format) G_GNUC_CONST; + +void gst_audio_format_fill_silence (const GstAudioFormatInfo *info, + gpointer dest, gsize length); + +#define GST_AUDIO_RATE_RANGE "(int) [ 1, max ]" +#define GST_AUDIO_CHANNELS_RANGE "(int) [ 1, max ]" + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +# define GST_AUDIO_NE(s) G_STRINGIFY(s)"LE" +# define GST_AUDIO_OE(s) G_STRINGIFY(s)"BE" +#else +# define GST_AUDIO_NE(s) G_STRINGIFY(s)"BE" +# define GST_AUDIO_OE(s) G_STRINGIFY(s)"LE" +#endif + +#define GST_AUDIO_FORMATS_ALL " { S8, U8, " \ + "S16LE, S16BE, U16LE, U16BE, " \ + "S24_32LE, S24_32BE, U24_32LE, U24_32BE, " \ + "S32LE, S32BE, U32LE, U32BE, " \ + "S24LE, S24BE, U24LE, U24BE, " \ + "S20LE, S20BE, U20LE, U20BE, " \ + "S18LE, S18BE, U18LE, U18BE, " \ + "F32LE, F32BE, F64LE, F64BE }" + +/** + * GST_AUDIO_CAPS_MAKE: + * @format: string format that describes the sample layout, as string + * (e.g. "S16LE", "S8", etc.) + * + * Generic caps string for audio, for use in pad templates. + */ +#define GST_AUDIO_CAPS_MAKE(format) \ + "audio/x-raw, " \ + "format = (string) " format ", " \ + "rate = " GST_AUDIO_RATE_RANGE ", " \ + "channels = " GST_AUDIO_CHANNELS_RANGE + +/** + * GST_AUDIO_DEF_RATE: + * + * Standard sampling rate used in consumer audio. + */ +#define GST_AUDIO_DEF_RATE 44100 +/** + * GST_AUDIO_DEF_CHANNELS: + * + * Standard number of channels used in consumer audio. + */ +#define GST_AUDIO_DEF_CHANNELS 2 +/** + * GST_AUDIO_DEF_FORMAT: + * + * Standard format used in consumer audio. + */ +#define GST_AUDIO_DEF_FORMAT "S16LE" + +G_END_DECLS + +#endif /* __GST_AUDIO_FORMAT_H__ */ diff --git a/gst-libs/gst/audio/audio-info.c b/gst-libs/gst/audio/audio-info.c new file mode 100644 index 0000000000..82c7fb0968 --- /dev/null +++ b/gst-libs/gst/audio/audio-info.c @@ -0,0 +1,460 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:gstaudio + * @short_description: Support library for audio elements + * + * This library contains some helper functions for audio elements. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#include "audio.h" + +#include + +/** + * gst_audio_info_copy: + * @info: a #GstAudioInfo + * + * Copy a GstAudioInfo structure. + * + * Returns: a new #GstAudioInfo. free with gst_audio_info_free. + */ +GstAudioInfo * +gst_audio_info_copy (const GstAudioInfo * info) +{ + return g_slice_dup (GstAudioInfo, info); +} + +/** + * gst_audio_info_free: + * @info: a #GstAudioInfo + * + * Free a GstAudioInfo structure previously allocated with gst_audio_info_new() + * or gst_audio_info_copy(). + */ +void +gst_audio_info_free (GstAudioInfo * info) +{ + g_slice_free (GstAudioInfo, info); +} + +G_DEFINE_BOXED_TYPE (GstAudioInfo, gst_audio_info, + (GBoxedCopyFunc) gst_audio_info_copy, (GBoxedFreeFunc) gst_audio_info_free); + +/** + * gst_audio_info_new: + * + * Allocate a new #GstAudioInfo that is also initialized with + * gst_audio_info_init(). + * + * Returns: a new #GstAudioInfo. free with gst_audio_info_free(). + */ +GstAudioInfo * +gst_audio_info_new (void) +{ + GstAudioInfo *info; + + info = g_slice_new (GstAudioInfo); + gst_audio_info_init (info); + + return info; +} + +/** + * gst_audio_info_init: + * @info: a #GstAudioInfo + * + * Initialize @info with default values. + */ +void +gst_audio_info_init (GstAudioInfo * info) +{ + g_return_if_fail (info != NULL); + + memset (info, 0, sizeof (GstAudioInfo)); + + info->finfo = gst_audio_format_get_info (GST_AUDIO_FORMAT_UNKNOWN); + + memset (&info->position, 0xff, sizeof (info->position)); +} + +/** + * gst_audio_info_set_format: + * @info: a #GstAudioInfo + * @format: the format + * @rate: the samplerate + * @channels: the number of channels + * @position: the channel positions + * + * Set the default info for the audio info of @format and @rate and @channels. + */ +void +gst_audio_info_set_format (GstAudioInfo * info, GstAudioFormat format, + gint rate, gint channels, const GstAudioChannelPosition * position) +{ + const GstAudioFormatInfo *finfo; + gint i; + + g_return_if_fail (info != NULL); + g_return_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN); + + finfo = gst_audio_format_get_info (format); + + info->flags = 0; + info->layout = GST_AUDIO_LAYOUT_INTERLEAVED; + info->finfo = finfo; + info->rate = rate; + info->channels = channels; + info->bpf = (finfo->width * channels) / 8; + + memset (&info->position, 0xff, sizeof (info->position)); + + if (!position && channels == 1) { + info->position[0] = GST_AUDIO_CHANNEL_POSITION_MONO; + return; + } else if (!position && channels == 2) { + info->position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; + info->position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; + return; + } else { + if (!position + || !gst_audio_check_valid_channel_positions (position, channels, + TRUE)) { + if (position) + g_warning ("Invalid channel positions"); + } else { + memcpy (&info->position, position, + info->channels * sizeof (info->position[0])); + if (info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) + info->flags |= GST_AUDIO_FLAG_UNPOSITIONED; + return; + } + } + + /* Otherwise a NONE layout */ + info->flags |= GST_AUDIO_FLAG_UNPOSITIONED; + for (i = 0; i < MIN (64, channels); i++) + info->position[i] = GST_AUDIO_CHANNEL_POSITION_NONE; +} + +/** + * gst_audio_info_from_caps: + * @info: a #GstAudioInfo + * @caps: a #GstCaps + * + * Parse @caps and update @info. + * + * Returns: TRUE if @caps could be parsed + */ +gboolean +gst_audio_info_from_caps (GstAudioInfo * info, const GstCaps * caps) +{ + GstStructure *str; + const gchar *s; + GstAudioFormat format; + gint rate, channels; + guint64 channel_mask; + gint i; + GstAudioChannelPosition position[64]; + + g_return_val_if_fail (info != NULL, FALSE); + g_return_val_if_fail (caps != NULL, FALSE); + g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); + + GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps); + + info->flags = 0; + + str = gst_caps_get_structure (caps, 0); + + if (!gst_structure_has_name (str, "audio/x-raw")) + goto wrong_name; + + if (!(s = gst_structure_get_string (str, "format"))) + goto no_format; + + format = gst_audio_format_from_string (s); + if (format == GST_AUDIO_FORMAT_UNKNOWN) + goto unknown_format; + + if (!(s = gst_structure_get_string (str, "layout"))) + goto no_layout; + if (g_str_equal (s, "interleaved")) + info->layout = GST_AUDIO_LAYOUT_INTERLEAVED; + else if (g_str_equal (s, "non-interleaved")) + info->layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; + else + goto unknown_layout; + + if (!gst_structure_get_int (str, "rate", &rate)) + goto no_rate; + if (!gst_structure_get_int (str, "channels", &channels)) + goto no_channels; + + if (!gst_structure_get (str, "channel-mask", GST_TYPE_BITMASK, &channel_mask, + NULL)) { + if (channels == 1) { + position[0] = GST_AUDIO_CHANNEL_POSITION_MONO; + } else if (channels == 2) { + position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; + position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; + } else { + goto no_channel_mask; + } + } else if (channel_mask == 0) { + info->flags |= GST_AUDIO_FLAG_UNPOSITIONED; + for (i = 0; i < MIN (64, channels); i++) + position[i] = GST_AUDIO_CHANNEL_POSITION_NONE; + } else { + if (!gst_audio_channel_positions_from_mask (channels, channel_mask, + position)) + goto invalid_channel_mask; + } + + gst_audio_info_set_format (info, format, rate, channels, position); + + return TRUE; + + /* ERROR */ +wrong_name: + { + GST_ERROR ("wrong name, expected audio/x-raw"); + return FALSE; + } +no_format: + { + GST_ERROR ("no format given"); + return FALSE; + } +unknown_format: + { + GST_ERROR ("unknown format given"); + return FALSE; + } +no_layout: + { + GST_ERROR ("no layout given"); + return FALSE; + } +unknown_layout: + { + GST_ERROR ("unknown layout given"); + return FALSE; + } +no_rate: + { + GST_ERROR ("no rate property given"); + return FALSE; + } +no_channels: + { + GST_ERROR ("no channels property given"); + return FALSE; + } +no_channel_mask: + { + GST_ERROR ("no channel-mask property given"); + return FALSE; + } +invalid_channel_mask: + { + GST_ERROR ("Invalid channel mask 0x%016" G_GINT64_MODIFIER + "x for %d channels", channel_mask, channels); + return FALSE; + } +} + +/** + * gst_audio_info_to_caps: + * @info: a #GstAudioInfo + * + * Convert the values of @info into a #GstCaps. + * + * Returns: (transfer full): the new #GstCaps containing the + * info of @info. + */ +GstCaps * +gst_audio_info_to_caps (const GstAudioInfo * info) +{ + GstCaps *caps; + const gchar *format; + const gchar *layout; + GstAudioFlags flags; + + g_return_val_if_fail (info != NULL, NULL); + g_return_val_if_fail (info->finfo != NULL, NULL); + g_return_val_if_fail (info->finfo->format != GST_AUDIO_FORMAT_UNKNOWN, NULL); + + format = gst_audio_format_to_string (info->finfo->format); + g_return_val_if_fail (format != NULL, NULL); + + if (info->layout == GST_AUDIO_LAYOUT_INTERLEAVED) + layout = "interleaved"; + else if (info->layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) + layout = "non-interleaved"; + else + g_return_val_if_reached (NULL); + + flags = info->flags; + if ((flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1 + && info->position[0] != GST_AUDIO_CHANNEL_POSITION_NONE) { + flags &= ~GST_AUDIO_FLAG_UNPOSITIONED; + g_warning ("Unpositioned audio channel position flag set but " + "channel positions present"); + } else if (!(flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1 + && info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { + flags |= GST_AUDIO_FLAG_UNPOSITIONED; + g_warning ("Unpositioned audio channel position flag not set " + "but no channel positions present"); + } + + caps = gst_caps_new_simple ("audio/x-raw", + "format", G_TYPE_STRING, format, + "layout", G_TYPE_STRING, layout, + "rate", G_TYPE_INT, info->rate, + "channels", G_TYPE_INT, info->channels, NULL); + + if (info->channels > 1 + || info->position[0] != GST_AUDIO_CHANNEL_POSITION_MONO) { + guint64 channel_mask = 0; + + if ((flags & GST_AUDIO_FLAG_UNPOSITIONED)) { + channel_mask = 0; + } else { + if (!gst_audio_channel_positions_to_mask (info->position, info->channels, + TRUE, &channel_mask)) + goto invalid_channel_positions; + } + + if (info->channels == 1 + && info->position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) { + /* Default mono special case */ + } else { + gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, + NULL); + } + } + + return caps; + +invalid_channel_positions: + { + GST_ERROR ("Invalid channel positions"); + gst_caps_unref (caps); + return NULL; + } +} + +/** + * gst_audio_info_convert: + * @info: a #GstAudioInfo + * @src_format: #GstFormat of the @src_value + * @src_value: value to convert + * @dest_format: #GstFormat of the @dest_value + * @dest_value: pointer to destination value + * + * Converts among various #GstFormat types. This function handles + * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For + * raw audio, GST_FORMAT_DEFAULT corresponds to audio frames. This + * function can be used to handle pad queries of the type GST_QUERY_CONVERT. + * + * Returns: TRUE if the conversion was successful. + */ +gboolean +gst_audio_info_convert (const GstAudioInfo * info, + GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val) +{ + gboolean res = TRUE; + gint bpf, rate; + + GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)", + src_val, gst_format_get_name (src_fmt), src_fmt, + gst_format_get_name (dest_fmt), dest_fmt); + + if (src_fmt == dest_fmt || src_val == -1) { + *dest_val = src_val; + goto done; + } + + /* get important info */ + bpf = GST_AUDIO_INFO_BPF (info); + rate = GST_AUDIO_INFO_RATE (info); + + if (bpf == 0 || rate == 0) { + GST_DEBUG ("no rate or bpf configured"); + res = FALSE; + goto done; + } + + switch (src_fmt) { + case GST_FORMAT_BYTES: + switch (dest_fmt) { + case GST_FORMAT_TIME: + *dest_val = GST_FRAMES_TO_CLOCK_TIME (src_val / bpf, rate); + break; + case GST_FORMAT_DEFAULT: + *dest_val = src_val / bpf; + break; + default: + res = FALSE; + break; + } + break; + case GST_FORMAT_DEFAULT: + switch (dest_fmt) { + case GST_FORMAT_TIME: + *dest_val = GST_FRAMES_TO_CLOCK_TIME (src_val, rate); + break; + case GST_FORMAT_BYTES: + *dest_val = src_val * bpf; + break; + default: + res = FALSE; + break; + } + break; + case GST_FORMAT_TIME: + switch (dest_fmt) { + case GST_FORMAT_DEFAULT: + *dest_val = GST_CLOCK_TIME_TO_FRAMES (src_val, rate); + break; + case GST_FORMAT_BYTES: + *dest_val = GST_CLOCK_TIME_TO_FRAMES (src_val, rate); + *dest_val *= bpf; + break; + default: + res = FALSE; + break; + } + break; + default: + res = FALSE; + break; + } +done: + GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val); + + return res; +} diff --git a/gst-libs/gst/audio/audio-info.h b/gst-libs/gst/audio/audio-info.h new file mode 100644 index 0000000000..fb6ab260c3 --- /dev/null +++ b/gst-libs/gst/audio/audio-info.h @@ -0,0 +1,133 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * Library <2001> Thomas Vander Stichele + * <2011> 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUDIO_INFO_H__ +#define __GST_AUDIO_INFO_H__ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +typedef struct _GstAudioInfo GstAudioInfo; + +/** + * GstAudioFlags: + * @GST_AUDIO_FLAG_NONE: no valid flag + * @GST_AUDIO_FLAG_UNPOSITIONED: the position array explicitly + * contains unpositioned channels. + * + * Extra audio flags + */ +typedef enum { + GST_AUDIO_FLAG_NONE = 0, + GST_AUDIO_FLAG_UNPOSITIONED = (1 << 0) +} GstAudioFlags; + +/** + * GstAudioLayout: + * @GST_AUDIO_LAYOUT_INTERLEAVED: interleaved audio + * @GST_AUDIO_LAYOUT_NON_INTERLEAVED: non-interleaved audio + * + * Layout of the audio samples for the different channels. + */ +typedef enum { + GST_AUDIO_LAYOUT_INTERLEAVED = 0, + GST_AUDIO_LAYOUT_NON_INTERLEAVED +} GstAudioLayout; + +/** + * GstAudioInfo: + * @finfo: the format info of the audio + * @flags: additional audio flags + * @layout: audio layout + * @rate: the audio sample rate + * @channels: the number of channels + * @bpf: the number of bytes for one frame, this is the size of one + * sample * @channels + * @position: the positions for each channel + * + * Information describing audio properties. This information can be filled + * in from GstCaps with gst_audio_info_from_caps(). + * + * Use the provided macros to access the info in this structure. + */ +struct _GstAudioInfo { + const GstAudioFormatInfo *finfo; + GstAudioFlags flags; + GstAudioLayout layout; + gint rate; + gint channels; + gint bpf; + GstAudioChannelPosition position[64]; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING]; +}; + +GType gst_audio_info_get_type (void); + +#define GST_AUDIO_INFO_IS_VALID(i) ((i)->finfo != NULL && (i)->rate > 0 && (i)->channels > 0 && (i)->bpf > 0) + +#define GST_AUDIO_INFO_FORMAT(i) (GST_AUDIO_FORMAT_INFO_FORMAT((i)->finfo)) +#define GST_AUDIO_INFO_NAME(i) (GST_AUDIO_FORMAT_INFO_NAME((i)->finfo)) +#define GST_AUDIO_INFO_WIDTH(i) (GST_AUDIO_FORMAT_INFO_WIDTH((i)->finfo)) +#define GST_AUDIO_INFO_DEPTH(i) (GST_AUDIO_FORMAT_INFO_DEPTH((i)->finfo)) +#define GST_AUDIO_INFO_BPS(info) (GST_AUDIO_INFO_DEPTH(info) >> 3) + +#define GST_AUDIO_INFO_IS_INTEGER(i) (GST_AUDIO_FORMAT_INFO_IS_INTEGER((i)->finfo)) +#define GST_AUDIO_INFO_IS_FLOAT(i) (GST_AUDIO_FORMAT_INFO_IS_FLOAT((i)->finfo)) +#define GST_AUDIO_INFO_IS_SIGNED(i) (GST_AUDIO_FORMAT_INFO_IS_SIGNED((i)->finfo)) + +#define GST_AUDIO_INFO_ENDIANNESS(i) (GST_AUDIO_FORMAT_INFO_ENDIANNES((i)->finfo)) +#define GST_AUDIO_INFO_IS_LITTLE_ENDIAN(i) (GST_AUDIO_FORMAT_INFO_IS_LITTLE_ENDIAN((i)->finfo)) +#define GST_AUDIO_INFO_IS_BIG_ENDIAN(i) (GST_AUDIO_FORMAT_INFO_IS_BIG_ENDIAN((i)->finfo)) + +#define GST_AUDIO_INFO_FLAGS(info) ((info)->flags) +#define GST_AUDIO_INFO_IS_UNPOSITIONED(info) ((info)->flags & GST_AUDIO_FLAG_UNPOSITIONED) +#define GST_AUDIO_INFO_LAYOUT(info) ((info)->layout) + +#define GST_AUDIO_INFO_RATE(info) ((info)->rate) +#define GST_AUDIO_INFO_CHANNELS(info) ((info)->channels) +#define GST_AUDIO_INFO_BPF(info) ((info)->bpf) +#define GST_AUDIO_INFO_POSITION(info,c) ((info)->position[c]) + +GstAudioInfo * gst_audio_info_new (void); +void gst_audio_info_init (GstAudioInfo *info); +GstAudioInfo * gst_audio_info_copy (const GstAudioInfo *info); +void gst_audio_info_free (GstAudioInfo *info); + +void gst_audio_info_set_format (GstAudioInfo *info, GstAudioFormat format, + gint rate, gint channels, + const GstAudioChannelPosition *position); + +gboolean gst_audio_info_from_caps (GstAudioInfo *info, const GstCaps *caps); +GstCaps * gst_audio_info_to_caps (const GstAudioInfo *info); + +gboolean gst_audio_info_convert (const GstAudioInfo * info, + GstFormat src_fmt, gint64 src_val, + GstFormat dest_fmt, gint64 * dest_val); + +G_END_DECLS + +#endif /* __GST_AUDIO_INFO_H__ */ diff --git a/gst-libs/gst/audio/audio.c b/gst-libs/gst/audio/audio.c index 15fcc5b53e..3d6b07f19e 100644 --- a/gst-libs/gst/audio/audio.c +++ b/gst-libs/gst/audio/audio.c @@ -32,777 +32,6 @@ #include "audio.h" #include "audio-enumtypes.h" -#include - -#define SINT (GST_AUDIO_FORMAT_FLAG_INTEGER | GST_AUDIO_FORMAT_FLAG_SIGNED) -#define UINT (GST_AUDIO_FORMAT_FLAG_INTEGER) - -#define MAKE_FORMAT(str,desc,flags,end,width,depth,silent) \ - { GST_AUDIO_FORMAT_ ##str, G_STRINGIFY(str), desc, flags, end, width, depth, silent } - -#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 GstAudioFormatInfo formats[] = { - {GST_AUDIO_FORMAT_UNKNOWN, "UNKNOWN", 0, 0, 0, 0}, - /* 8 bit */ - MAKE_FORMAT (S8, "8-bit signed PCM audio", SINT, 0, 8, 8, SILENT_0), - MAKE_FORMAT (U8, "8-bit unsigned PCM audio", UINT, 0, 8, 8, SILENT_U8), - /* 16 bit */ - MAKE_FORMAT (S16LE, "16-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 16, 16, - SILENT_0), - MAKE_FORMAT (S16BE, "16-bit signed PCM audio", SINT, G_BIG_ENDIAN, 16, 16, - SILENT_0), - MAKE_FORMAT (U16LE, "16-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 16, - 16, SILENT_U16LE), - MAKE_FORMAT (U16BE, "16-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 16, 16, - SILENT_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), - MAKE_FORMAT (S24_32BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32, 24, - SILENT_0), - MAKE_FORMAT (U24_32LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 32, - 24, SILENT_U24_32LE), - MAKE_FORMAT (U24_32BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32, - 24, SILENT_U24_32BE), - /* 32 bit */ - MAKE_FORMAT (S32LE, "32-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 32, 32, - SILENT_0), - MAKE_FORMAT (S32BE, "32-bit signed PCM audio", SINT, G_BIG_ENDIAN, 32, 32, - SILENT_0), - MAKE_FORMAT (U32LE, "32-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 32, - 32, SILENT_U32LE), - MAKE_FORMAT (U32BE, "32-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 32, 32, - SILENT_U32BE), - /* 24 bit in 3 bytes */ - MAKE_FORMAT (S24LE, "24-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 24, - SILENT_0), - MAKE_FORMAT (S24BE, "24-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 24, - SILENT_0), - MAKE_FORMAT (U24LE, "24-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, - 24, SILENT_U24LE), - MAKE_FORMAT (U24BE, "24-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 24, - SILENT_U24BE), - /* 20 bit in 3 bytes */ - MAKE_FORMAT (S20LE, "20-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 20, - SILENT_0), - MAKE_FORMAT (S20BE, "20-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 20, - SILENT_0), - MAKE_FORMAT (U20LE, "20-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, - 20, SILENT_U20LE), - MAKE_FORMAT (U20BE, "20-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 20, - SILENT_U20BE), - /* 18 bit in 3 bytes */ - MAKE_FORMAT (S18LE, "18-bit signed PCM audio", SINT, G_LITTLE_ENDIAN, 24, 18, - SILENT_0), - MAKE_FORMAT (S18BE, "18-bit signed PCM audio", SINT, G_BIG_ENDIAN, 24, 18, - SILENT_0), - MAKE_FORMAT (U18LE, "18-bit unsigned PCM audio", UINT, G_LITTLE_ENDIAN, 24, - 18, SILENT_U18LE), - MAKE_FORMAT (U18BE, "18-bit unsigned PCM audio", UINT, G_BIG_ENDIAN, 24, 18, - SILENT_U18BE), - /* float */ - MAKE_FORMAT (F32LE, "32-bit floating-point audio", - GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 32, 32, - SILENT_0), - MAKE_FORMAT (F32BE, "32-bit floating-point audio", - GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 32, 32, - SILENT_0), - MAKE_FORMAT (F64LE, "64-bit floating-point audio", - GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 64, 64, - SILENT_0), - MAKE_FORMAT (F64BE, "64-bit floating-point audio", - GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 64, 64, - SILENT_0) -}; - -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++) { - 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; - - 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; -} - -const gchar * -gst_audio_format_to_string (GstAudioFormat format) -{ - g_return_val_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN, NULL); - - if (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 (format != GST_AUDIO_FORMAT_UNKNOWN, NULL); - g_return_val_if_fail (format < G_N_ELEMENTS (formats), NULL); - - return &formats[format]; -} - -/** - * gst_audio_format_fill_silence: - * @info: a #GstAudioFormatInfo - * @dest: a destination to fill - * @length: the length to fill - * - * Fill @length bytes in @dest with silence samples for @info. - */ -void -gst_audio_format_fill_silence (const GstAudioFormatInfo * info, - gpointer dest, gsize length) -{ - guint8 *dptr = dest; - - g_return_if_fail (info != NULL); - 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 */ - memset (dest, 0, length); - } else { - gint i, j, bps = info->width >> 3; - - switch (bps) { - case 1: - memset (dest, info->silence[0], length); - break; - default: - for (i = 0; i < length; i += bps) { - for (j = 0; j < bps; j++) - *dptr++ = info->silence[j]; - } - break; - } - } -} - -/** - * gst_audio_info_copy: - * @info: a #GstAudioInfo - * - * Copy a GstAudioInfo structure. - * - * Returns: a new #GstAudioInfo. free with gst_audio_info_free. - */ -GstAudioInfo * -gst_audio_info_copy (const GstAudioInfo * info) -{ - return g_slice_dup (GstAudioInfo, info); -} - -/** - * gst_audio_info_free: - * @info: a #GstAudioInfo - * - * Free a GstAudioInfo structure previously allocated with gst_audio_info_new() - * or gst_audio_info_copy(). - */ -void -gst_audio_info_free (GstAudioInfo * info) -{ - g_slice_free (GstAudioInfo, info); -} - -G_DEFINE_BOXED_TYPE (GstAudioInfo, gst_audio_info, - (GBoxedCopyFunc) gst_audio_info_copy, (GBoxedFreeFunc) gst_audio_info_free); - -/** - * gst_audio_info_new: - * - * Allocate a new #GstAudioInfo that is also initialized with - * gst_audio_info_init(). - * - * Returns: a new #GstAudioInfo. free with gst_audio_info_free(). - */ -GstAudioInfo * -gst_audio_info_new (void) -{ - GstAudioInfo *info; - - info = g_slice_new (GstAudioInfo); - gst_audio_info_init (info); - - return info; -} - -/** - * gst_audio_info_init: - * @info: a #GstAudioInfo - * - * Initialize @info with default values. - */ -void -gst_audio_info_init (GstAudioInfo * info) -{ - g_return_if_fail (info != NULL); - - memset (info, 0, sizeof (GstAudioInfo)); - - info->finfo = &formats[GST_AUDIO_FORMAT_UNKNOWN]; - - memset (&info->position, 0xff, sizeof (info->position)); -} - -static const GstAudioChannelPosition default_channel_order[64] = { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE1, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, - GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE2, - GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, - GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER, - GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT, - GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT, - GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID, - GST_AUDIO_CHANNEL_POSITION_INVALID -}; - -static gboolean -check_valid_channel_positions (const GstAudioChannelPosition * position, - gint channels, gboolean enforce_order, guint64 * channel_mask_out) -{ - gint i, j; - guint64 channel_mask = 0; - - if (channels == 1 && position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) { - if (channel_mask_out) - *channel_mask_out = 0; - return TRUE; - } - - if (channels > 0 && position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { - if (channel_mask_out) - *channel_mask_out = 0; - return TRUE; - } - - j = 0; - for (i = 0; i < channels; i++) { - while (j < G_N_ELEMENTS (default_channel_order) - && default_channel_order[j] != position[i]) - j++; - - if (position[i] == GST_AUDIO_CHANNEL_POSITION_INVALID || - position[i] == GST_AUDIO_CHANNEL_POSITION_MONO || - position[i] == GST_AUDIO_CHANNEL_POSITION_NONE) - return FALSE; - - /* Is this in valid channel order? */ - if (enforce_order && j == G_N_ELEMENTS (default_channel_order)) - return FALSE; - j++; - - if ((channel_mask & (G_GUINT64_CONSTANT (1) << position[i]))) - return FALSE; - - channel_mask |= (G_GUINT64_CONSTANT (1) << position[i]); - } - - if (channel_mask_out) - *channel_mask_out = channel_mask; - - return TRUE; -} - -/** - * gst_audio_info_set_format: - * @info: a #GstAudioInfo - * @format: the format - * @rate: the samplerate - * @channels: the number of channels - * @position: the channel positions - * - * Set the default info for the audio info of @format and @rate and @channels. - */ -void -gst_audio_info_set_format (GstAudioInfo * info, GstAudioFormat format, - gint rate, gint channels, const GstAudioChannelPosition * position) -{ - const GstAudioFormatInfo *finfo; - gint i; - - g_return_if_fail (info != NULL); - g_return_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN); - - finfo = &formats[format]; - - info->flags = 0; - info->layout = GST_AUDIO_LAYOUT_INTERLEAVED; - info->finfo = finfo; - info->rate = rate; - info->channels = channels; - info->bpf = (finfo->width * channels) / 8; - - memset (&info->position, 0xff, sizeof (info->position)); - - if (!position && channels == 1) { - info->position[0] = GST_AUDIO_CHANNEL_POSITION_MONO; - return; - } else if (!position && channels == 2) { - info->position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; - info->position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; - return; - } else { - if (!position - || !check_valid_channel_positions (position, channels, TRUE, NULL)) { - if (position) - g_warning ("Invalid channel positions"); - } else { - memcpy (&info->position, position, - info->channels * sizeof (info->position[0])); - if (info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) - info->flags |= GST_AUDIO_FLAG_UNPOSITIONED; - return; - } - } - - /* Otherwise a NONE layout */ - info->flags |= GST_AUDIO_FLAG_UNPOSITIONED; - for (i = 0; i < MIN (64, channels); i++) - info->position[i] = GST_AUDIO_CHANNEL_POSITION_NONE; -} - -/** - * gst_audio_info_from_caps: - * @info: a #GstAudioInfo - * @caps: a #GstCaps - * - * Parse @caps and update @info. - * - * Returns: TRUE if @caps could be parsed - */ -gboolean -gst_audio_info_from_caps (GstAudioInfo * info, const GstCaps * caps) -{ - GstStructure *str; - const gchar *s; - GstAudioFormat format; - gint rate, channels; - guint64 channel_mask; - gint i; - GstAudioChannelPosition position[64]; - - g_return_val_if_fail (info != NULL, FALSE); - g_return_val_if_fail (caps != NULL, FALSE); - g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE); - - GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps); - - info->flags = 0; - - str = gst_caps_get_structure (caps, 0); - - if (!gst_structure_has_name (str, "audio/x-raw")) - goto wrong_name; - - if (!(s = gst_structure_get_string (str, "format"))) - goto no_format; - - format = gst_audio_format_from_string (s); - if (format == GST_AUDIO_FORMAT_UNKNOWN) - goto unknown_format; - - if (!(s = gst_structure_get_string (str, "layout"))) - goto no_layout; - if (g_str_equal (s, "interleaved")) - info->layout = GST_AUDIO_LAYOUT_INTERLEAVED; - else if (g_str_equal (s, "non-interleaved")) - info->layout = GST_AUDIO_LAYOUT_NON_INTERLEAVED; - else - goto unknown_layout; - - if (!gst_structure_get_int (str, "rate", &rate)) - goto no_rate; - if (!gst_structure_get_int (str, "channels", &channels)) - goto no_channels; - - if (!gst_structure_get (str, "channel-mask", GST_TYPE_BITMASK, &channel_mask, - NULL)) { - if (channels == 1) { - position[0] = GST_AUDIO_CHANNEL_POSITION_MONO; - } else if (channels == 2) { - position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; - position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; - } else { - goto no_channel_mask; - } - } else if (channel_mask == 0) { - info->flags |= GST_AUDIO_FLAG_UNPOSITIONED; - for (i = 0; i < MIN (64, channels); i++) - position[i] = GST_AUDIO_CHANNEL_POSITION_NONE; - } else { - if (!gst_audio_channel_positions_from_mask (channels, channel_mask, - position)) - goto invalid_channel_mask; - } - - gst_audio_info_set_format (info, format, rate, channels, position); - - return TRUE; - - /* ERROR */ -wrong_name: - { - GST_ERROR ("wrong name, expected audio/x-raw"); - return FALSE; - } -no_format: - { - GST_ERROR ("no format given"); - return FALSE; - } -unknown_format: - { - GST_ERROR ("unknown format given"); - return FALSE; - } -no_layout: - { - GST_ERROR ("no layout given"); - return FALSE; - } -unknown_layout: - { - GST_ERROR ("unknown layout given"); - return FALSE; - } -no_rate: - { - GST_ERROR ("no rate property given"); - return FALSE; - } -no_channels: - { - GST_ERROR ("no channels property given"); - return FALSE; - } -no_channel_mask: - { - GST_ERROR ("no channel-mask property given"); - return FALSE; - } -invalid_channel_mask: - { - GST_ERROR ("Invalid channel mask 0x%016" G_GINT64_MODIFIER - "x for %d channels", channel_mask, channels); - return FALSE; - } -} - -/** - * gst_audio_info_to_caps: - * @info: a #GstAudioInfo - * - * Convert the values of @info into a #GstCaps. - * - * Returns: (transfer full): the new #GstCaps containing the - * info of @info. - */ -GstCaps * -gst_audio_info_to_caps (const GstAudioInfo * info) -{ - GstCaps *caps; - const gchar *format; - const gchar *layout; - GstAudioFlags flags; - - g_return_val_if_fail (info != NULL, NULL); - g_return_val_if_fail (info->finfo != NULL, NULL); - g_return_val_if_fail (info->finfo->format != GST_AUDIO_FORMAT_UNKNOWN, NULL); - - format = gst_audio_format_to_string (info->finfo->format); - g_return_val_if_fail (format != NULL, NULL); - - if (info->layout == GST_AUDIO_LAYOUT_INTERLEAVED) - layout = "interleaved"; - else if (info->layout == GST_AUDIO_LAYOUT_NON_INTERLEAVED) - layout = "non-interleaved"; - else - g_return_val_if_reached (NULL); - - flags = info->flags; - if ((flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1 - && info->position[0] != GST_AUDIO_CHANNEL_POSITION_NONE) { - flags &= ~GST_AUDIO_FLAG_UNPOSITIONED; - g_warning ("Unpositioned audio channel position flag set but " - "channel positions present"); - } else if (!(flags & GST_AUDIO_FLAG_UNPOSITIONED) && info->channels > 1 - && info->position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) { - flags |= GST_AUDIO_FLAG_UNPOSITIONED; - g_warning ("Unpositioned audio channel position flag not set " - "but no channel positions present"); - } - - caps = gst_caps_new_simple ("audio/x-raw", - "format", G_TYPE_STRING, format, - "layout", G_TYPE_STRING, layout, - "rate", G_TYPE_INT, info->rate, - "channels", G_TYPE_INT, info->channels, NULL); - - if (info->channels > 1 - || info->position[0] != GST_AUDIO_CHANNEL_POSITION_MONO) { - guint64 channel_mask = 0; - - if ((flags & GST_AUDIO_FLAG_UNPOSITIONED)) { - channel_mask = 0; - } else { - if (!check_valid_channel_positions (info->position, info->channels, - TRUE, &channel_mask)) - goto invalid_channel_positions; - } - - if (info->channels == 1 - && info->position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) { - /* Default mono special case */ - } else { - gst_caps_set_simple (caps, "channel-mask", GST_TYPE_BITMASK, channel_mask, - NULL); - } - } - - return caps; - -invalid_channel_positions: - { - GST_ERROR ("Invalid channel positions"); - gst_caps_unref (caps); - return NULL; - } -} - -/** - * gst_audio_format_convert: - * @info: a #GstAudioInfo - * @src_format: #GstFormat of the @src_value - * @src_value: value to convert - * @dest_format: #GstFormat of the @dest_value - * @dest_value: pointer to destination value - * - * Converts among various #GstFormat types. This function handles - * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For - * raw audio, GST_FORMAT_DEFAULT corresponds to audio frames. This - * function can be used to handle pad queries of the type GST_QUERY_CONVERT. - * - * Returns: TRUE if the conversion was successful. - */ -gboolean -gst_audio_info_convert (const GstAudioInfo * info, - GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val) -{ - gboolean res = TRUE; - gint bpf, rate; - - GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)", - src_val, gst_format_get_name (src_fmt), src_fmt, - gst_format_get_name (dest_fmt), dest_fmt); - - if (src_fmt == dest_fmt || src_val == -1) { - *dest_val = src_val; - goto done; - } - - /* get important info */ - bpf = GST_AUDIO_INFO_BPF (info); - rate = GST_AUDIO_INFO_RATE (info); - - if (bpf == 0 || rate == 0) { - GST_DEBUG ("no rate or bpf configured"); - res = FALSE; - goto done; - } - - switch (src_fmt) { - case GST_FORMAT_BYTES: - switch (dest_fmt) { - case GST_FORMAT_TIME: - *dest_val = GST_FRAMES_TO_CLOCK_TIME (src_val / bpf, rate); - break; - case GST_FORMAT_DEFAULT: - *dest_val = src_val / bpf; - break; - default: - res = FALSE; - break; - } - break; - case GST_FORMAT_DEFAULT: - switch (dest_fmt) { - case GST_FORMAT_TIME: - *dest_val = GST_FRAMES_TO_CLOCK_TIME (src_val, rate); - break; - case GST_FORMAT_BYTES: - *dest_val = src_val * bpf; - break; - default: - res = FALSE; - break; - } - break; - case GST_FORMAT_TIME: - switch (dest_fmt) { - case GST_FORMAT_DEFAULT: - *dest_val = GST_CLOCK_TIME_TO_FRAMES (src_val, rate); - break; - case GST_FORMAT_BYTES: - *dest_val = GST_CLOCK_TIME_TO_FRAMES (src_val, rate); - *dest_val *= bpf; - break; - default: - res = FALSE; - break; - } - break; - default: - res = FALSE; - break; - } -done: - GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val); - - return res; -} - /** * gst_audio_buffer_clip: * @buffer: The buffer to clip. @@ -974,317 +203,3 @@ gst_audio_buffer_clip (GstBuffer * buffer, GstSegment * segment, gint rate, } return ret; } - -/** - * gst_audio_reorder_channels: - * @data: The pointer to the memory. - * @size: The size of the memory. - * @format: The %GstAudioFormat of the buffer. - * @channels: The number of channels. - * @from: The channel positions in the buffer. - * @to: The channel positions to convert to. - * - * Reorders @data from the channel positions @from to the channel - * positions @to. @from and @to must contain the same number of - * positions and the same positions, only in a different order. - * - * Returns: %TRUE if the reordering was possible. - */ -gboolean -gst_audio_reorder_channels (gpointer data, gsize size, GstAudioFormat format, - gint channels, const GstAudioChannelPosition * from, - const GstAudioChannelPosition * to) -{ - const GstAudioFormatInfo *info; - gint i, j, n; - gint reorder_map[64] = { 0, }; - guint8 *ptr; - gint bpf, bps; - guint8 tmp[64 * 8]; - - info = gst_audio_format_get_info (format); - - g_return_val_if_fail (data != NULL, FALSE); - g_return_val_if_fail (from != NULL, FALSE); - g_return_val_if_fail (to != NULL, FALSE); - g_return_val_if_fail (info != NULL && info->width > 0, FALSE); - g_return_val_if_fail (info->width > 0, FALSE); - g_return_val_if_fail (info->width <= 8 * 64, FALSE); - g_return_val_if_fail (size % ((info->width * channels) / 8) == 0, FALSE); - g_return_val_if_fail (channels > 0, FALSE); - g_return_val_if_fail (channels <= 64, FALSE); - - if (size == 0) - return TRUE; - - if (memcmp (from, to, channels * sizeof (from[0])) == 0) - return TRUE; - - if (!gst_audio_get_channel_reorder_map (channels, from, to, reorder_map)) - return FALSE; - - bps = info->width / 8; - bpf = bps * channels; - ptr = data; - - n = size / bpf; - for (i = 0; i < n; i++) { - - memcpy (tmp, ptr, bpf); - for (j = 0; j < channels; j++) - memcpy (ptr + reorder_map[j] * bps, tmp + j * bps, bps); - - ptr += bpf; - } - - return TRUE; -} - -/** - * gst_audio_buffer_reorder_channels: - * @buffer: The buffer to reorder. - * @format: The %GstAudioFormat of the buffer. - * @channels: The number of channels. - * @from: The channel positions in the buffer. - * @to: The channel positions to convert to. - * - * Reorders @buffer from the channel positions @from to the channel - * positions @to. @from and @to must contain the same number of - * positions and the same positions, only in a different order. - * @buffer must be writable. - * - * Returns: %TRUE if the reordering was possible. - */ -gboolean -gst_audio_buffer_reorder_channels (GstBuffer * buffer, - GstAudioFormat format, gint channels, - const GstAudioChannelPosition * from, const GstAudioChannelPosition * to) -{ - GstMapInfo info; - gboolean ret; - - g_return_val_if_fail (GST_IS_BUFFER (buffer), FALSE); - g_return_val_if_fail (gst_buffer_is_writable (buffer), FALSE); - - gst_buffer_map (buffer, &info, GST_MAP_READWRITE); - - ret = - gst_audio_reorder_channels (info.data, info.size, format, channels, from, - to); - - gst_buffer_unmap (buffer, &info); - - return ret; -} - -/** - * gst_audio_check_valid_channel_positions: - * @position: The %GstAudioChannelPositions to check. - * @channels: The number of channels. - * @force_order: Only consider the GStreamer channel order. - * - * Checks if @position contains valid channel positions for - * @channels channels. If @force_order is %TRUE it additionally - * checks if the channels are in the order required by GStreamer. - * - * Returns: %TRUE if the channel positions are valid. - */ -gboolean -gst_audio_check_valid_channel_positions (const GstAudioChannelPosition * - position, gint channels, gboolean force_order) -{ - return check_valid_channel_positions (position, channels, force_order, NULL); -} - -/** - * gst_audio_channel_positions_to_mask: - * @position: The %GstAudioChannelPositions - * @channels: The number of channels. - * @channel_mask: the output channel mask - * - * Convert the @position array of @channels channels to a bitmask. - * - * Returns: %TRUE if the channel positions are valid and could be converted. - */ -gboolean -gst_audio_channel_positions_to_mask (const GstAudioChannelPosition * position, - gint channels, guint64 * channel_mask) -{ - return check_valid_channel_positions (position, channels, FALSE, - channel_mask); -} - -/** - * gst_audio_channel_positions_from_mask: - * @channels: The number of channels - * @channel_mask: The input channel_mask - * @position: The %GstAudioChannelPositions - * @caps: a #GstCaps - * - * Convert the @channels present in @channel_mask to a @position array - * (which should have at least @channels entries ensured by caller). - * If @channel_mask is set to 0, it is considered as 'not present' for purpose - * of conversion. - * - * Returns: %TRUE if channel and channel mask are valid and could be converted - */ -gboolean -gst_audio_channel_positions_from_mask (gint channels, guint64 channel_mask, - GstAudioChannelPosition * position) -{ - g_return_val_if_fail (position != NULL, FALSE); - g_return_val_if_fail (channels != 0, FALSE); - - GST_DEBUG ("converting %d channels for " - " channel mask 0x%016" G_GINT64_MODIFIER "x", channels, channel_mask); - - if (!channel_mask) { - if (channels == 1) { - position[0] = GST_AUDIO_CHANNEL_POSITION_MONO; - } else if (channels == 2) { - position[0] = GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT; - position[1] = GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT; - } else { - goto no_channel_mask; - } - } else { - gint i, j; - - j = 0; - for (i = 0; i < 64; i++) { - if ((channel_mask & (G_GUINT64_CONSTANT (1) << i))) { - if (j < channels) - position[j] = default_channel_order[i]; - if (default_channel_order[i] == GST_AUDIO_CHANNEL_POSITION_INVALID) - goto invalid_channel_mask; - j++; - } - } - - if (j != channels) - goto invalid_channel_mask; - } - - return TRUE; - - /* ERROR */ -no_channel_mask: - { - GST_ERROR ("no channel-mask property given"); - return FALSE; - } -invalid_channel_mask: - { - GST_ERROR ("Invalid channel mask 0x%016" G_GINT64_MODIFIER - "x for %d channels", channel_mask, channels); - return FALSE; - } -} - - -/** - * gst_audio_get_channel_reorder_map: - * @channels: The number of channels. - * @from: The channel positions to reorder from. - * @to: The channel positions to reorder to. - * @reorder_map: Pointer to the reorder map. - * - * Returns a reorder map for @from to @to that can be used in - * custom channel reordering code, e.g. to convert from or to the - * GStreamer channel order. @from and @to must contain the same - * number of positions and the same positions, only in a - * different order. - * - * The resulting @reorder_map can be used for reordering by assigning - * channel i of the input to channel reorder_map[i] of the output. - * - * Returns: %TRUE if the channel positions are valid and reordering - * is possible. - */ -gboolean -gst_audio_get_channel_reorder_map (gint channels, - const GstAudioChannelPosition * from, const GstAudioChannelPosition * to, - gint * reorder_map) -{ - gint i, j; - - g_return_val_if_fail (reorder_map != NULL, FALSE); - g_return_val_if_fail (channels > 0, FALSE); - g_return_val_if_fail (from != NULL, FALSE); - g_return_val_if_fail (to != NULL, FALSE); - g_return_val_if_fail (check_valid_channel_positions (from, channels, FALSE, - NULL), FALSE); - g_return_val_if_fail (check_valid_channel_positions (to, channels, FALSE, - NULL), FALSE); - - /* Build reorder map and check compatibility */ - for (i = 0; i < channels; i++) { - if (from[i] == GST_AUDIO_CHANNEL_POSITION_NONE - || to[i] == GST_AUDIO_CHANNEL_POSITION_NONE) - return FALSE; - if (from[i] == GST_AUDIO_CHANNEL_POSITION_INVALID - || to[i] == GST_AUDIO_CHANNEL_POSITION_INVALID) - return FALSE; - if (from[i] == GST_AUDIO_CHANNEL_POSITION_MONO - || to[i] == GST_AUDIO_CHANNEL_POSITION_MONO) - return FALSE; - - for (j = 0; j < channels; j++) { - if (from[i] == to[j]) { - reorder_map[i] = j; - break; - } - } - - /* Not all channels present in both */ - if (j == channels) - return FALSE; - } - - return TRUE; -} - -/** - * gst_audio_channel_positions_to_valid_order: - * @position: The channel positions to reorder to. - * @channels: The number of channels. - * - * Reorders the channel positions in @position from any order to - * the GStreamer channel order. - * - * Returns: %TRUE if the channel positions are valid and reordering - * was successful. - */ -gboolean -gst_audio_channel_positions_to_valid_order (GstAudioChannelPosition * position, - gint channels) -{ - GstAudioChannelPosition tmp[64]; - guint64 channel_mask = 0; - gint i, j; - - g_return_val_if_fail (channels > 0, FALSE); - g_return_val_if_fail (position != NULL, FALSE); - g_return_val_if_fail (check_valid_channel_positions (position, channels, - FALSE, NULL), FALSE); - - if (channels == 1 && position[0] == GST_AUDIO_CHANNEL_POSITION_MONO) - return TRUE; - if (position[0] == GST_AUDIO_CHANNEL_POSITION_NONE) - return TRUE; - - check_valid_channel_positions (position, channels, FALSE, &channel_mask); - - memset (tmp, 0xff, sizeof (tmp)); - j = 0; - for (i = 0; i < 64; i++) { - if ((channel_mask & (G_GUINT64_CONSTANT (1) << i))) { - tmp[j] = i; - j++; - } - } - - memcpy (position, tmp, sizeof (tmp[0]) * channels); - - return TRUE; -} diff --git a/gst-libs/gst/audio/audio.h b/gst-libs/gst/audio/audio.h index 5e34eae003..e97fc1ab6f 100644 --- a/gst-libs/gst/audio/audio.h +++ b/gst-libs/gst/audio/audio.h @@ -19,506 +19,16 @@ * Boston, MA 02111-1307, USA. */ -#include - #ifndef __GST_AUDIO_AUDIO_H__ #define __GST_AUDIO_AUDIO_H__ -G_BEGIN_DECLS - +#include #include +#include +#include +#include -#if G_BYTE_ORDER == G_BIG_ENDIAN -#define _GST_AUDIO_FORMAT_NE(fmt) GST_AUDIO_FORMAT_ ## fmt ## BE -#elif G_BYTE_ORDER == G_LITTLE_ENDIAN -#define _GST_AUDIO_FORMAT_NE(fmt) GST_AUDIO_FORMAT_ ## fmt ## LE -#endif - -/** - * GstAudioFormat: - * @GST_AUDIO_FORMAT_UNKNOWN: unknown audio format - * @GST_AUDIO_FORMAT_S8: 8 bits in 8 bits, signed - * @GST_AUDIO_FORMAT_U8: 8 bits in 8 bits, unsigned - * @GST_AUDIO_FORMAT_S16LE: 16 bits in 16 bits, signed, little endian - * @GST_AUDIO_FORMAT_S16BE: 16 bits in 16 bits, signed, big endian - * @GST_AUDIO_FORMAT_U16LE: 16 bits in 16 bits, unsigned, little endian - * @GST_AUDIO_FORMAT_U16BE: 16 bits in 16 bits, unsigned, big endian - * @GST_AUDIO_FORMAT_S24_32LE: 24 bits in 32 bits, signed, little endian - * @GST_AUDIO_FORMAT_S24_32BE: 24 bits in 32 bits, signed, big endian - * @GST_AUDIO_FORMAT_U24_32LE: 24 bits in 32 bits, unsigned, little endian - * @GST_AUDIO_FORMAT_U24_32BE: 24 bits in 32 bits, unsigned, big endian - * @GST_AUDIO_FORMAT_S32LE: 32 bits in 32 bits, signed, little endian - * @GST_AUDIO_FORMAT_S32BE: 32 bits in 32 bits, signed, big endian - * @GST_AUDIO_FORMAT_U32LE: 32 bits in 32 bits, unsigned, little endian - * @GST_AUDIO_FORMAT_U32BE: 32 bits in 32 bits, unsigned, big endian - * @GST_AUDIO_FORMAT_S24LE: 24 bits in 24 bits, signed, little endian - * @GST_AUDIO_FORMAT_S24BE: 24 bits in 24 bits, signed, big endian - * @GST_AUDIO_FORMAT_U24LE: 24 bits in 24 bits, unsigned, little endian - * @GST_AUDIO_FORMAT_U24BE: 24 bits in 24 bits, unsigned, big endian - * @GST_AUDIO_FORMAT_S20LE: 20 bits in 24 bits, signed, little endian - * @GST_AUDIO_FORMAT_S20BE: 20 bits in 24 bits, signed, big endian - * @GST_AUDIO_FORMAT_U20LE: 20 bits in 24 bits, unsigned, little endian - * @GST_AUDIO_FORMAT_U20BE: 20 bits in 24 bits, unsigned, big endian - * @GST_AUDIO_FORMAT_S18LE: 18 bits in 24 bits, signed, little endian - * @GST_AUDIO_FORMAT_S18BE: 18 bits in 24 bits, signed, big endian - * @GST_AUDIO_FORMAT_U18LE: 18 bits in 24 bits, unsigned, little endian - * @GST_AUDIO_FORMAT_U18BE: 18 bits in 24 bits, unsigned, big endian - * @GST_AUDIO_FORMAT_F32LE: 32-bit floating point samples, little endian - * @GST_AUDIO_FORMAT_F32BE: 32-bit floating point samples, big endian - * @GST_AUDIO_FORMAT_F64LE: 64-bit floating point samples, little endian - * @GST_AUDIO_FORMAT_F64BE: 64-bit floating point samples, big endian - * @GST_AUDIO_FORMAT_S16: 16 bits in 16 bits, signed, native endianness - * @GST_AUDIO_FORMAT_U16: 16 bits in 16 bits, unsigned, native endianness - * @GST_AUDIO_FORMAT_S24_32: 24 bits in 32 bits, signed, native endianness - * @GST_AUDIO_FORMAT_U24_32: 24 bits in 32 bits, unsigned, native endianness - * @GST_AUDIO_FORMAT_S32: 32 bits in 32 bits, signed, native endianness - * @GST_AUDIO_FORMAT_U32: 32 bits in 32 bits, unsigned, native endianness - * @GST_AUDIO_FORMAT_S24: 24 bits in 24 bits, signed, native endianness - * @GST_AUDIO_FORMAT_U24: 24 bits in 24 bits, unsigned, native endianness - * @GST_AUDIO_FORMAT_S20: 20 bits in 24 bits, signed, native endianness - * @GST_AUDIO_FORMAT_U20: 20 bits in 24 bits, unsigned, native endianness - * @GST_AUDIO_FORMAT_S18: 18 bits in 24 bits, signed, native endianness - * @GST_AUDIO_FORMAT_U18: 18 bits in 24 bits, unsigned, native endianness - * @GST_AUDIO_FORMAT_F32: 32-bit floating point samples, native endianness - * @GST_AUDIO_FORMAT_F64: 64-bit floating point samples, native endianness - * - * Enum value describing the most common audio formats. - */ -typedef enum { - GST_AUDIO_FORMAT_UNKNOWN, - /* 8 bit */ - GST_AUDIO_FORMAT_S8, - GST_AUDIO_FORMAT_U8, - /* 16 bit */ - GST_AUDIO_FORMAT_S16LE, - GST_AUDIO_FORMAT_S16BE, - GST_AUDIO_FORMAT_U16LE, - GST_AUDIO_FORMAT_U16BE, - /* 24 bit in low 3 bytes of 32 bits*/ - GST_AUDIO_FORMAT_S24_32LE, - GST_AUDIO_FORMAT_S24_32BE, - GST_AUDIO_FORMAT_U24_32LE, - GST_AUDIO_FORMAT_U24_32BE, - /* 32 bit */ - GST_AUDIO_FORMAT_S32LE, - GST_AUDIO_FORMAT_S32BE, - GST_AUDIO_FORMAT_U32LE, - GST_AUDIO_FORMAT_U32BE, - /* 24 bit in 3 bytes*/ - GST_AUDIO_FORMAT_S24LE, - GST_AUDIO_FORMAT_S24BE, - GST_AUDIO_FORMAT_U24LE, - GST_AUDIO_FORMAT_U24BE, - /* 20 bit in 3 bytes*/ - GST_AUDIO_FORMAT_S20LE, - GST_AUDIO_FORMAT_S20BE, - GST_AUDIO_FORMAT_U20LE, - GST_AUDIO_FORMAT_U20BE, - /* 18 bit in 3 bytes*/ - GST_AUDIO_FORMAT_S18LE, - GST_AUDIO_FORMAT_S18BE, - GST_AUDIO_FORMAT_U18LE, - GST_AUDIO_FORMAT_U18BE, - /* float */ - GST_AUDIO_FORMAT_F32LE, - GST_AUDIO_FORMAT_F32BE, - GST_AUDIO_FORMAT_F64LE, - GST_AUDIO_FORMAT_F64BE, - /* native endianness equivalents */ - GST_AUDIO_FORMAT_S16 = _GST_AUDIO_FORMAT_NE(S16), - GST_AUDIO_FORMAT_U16 = _GST_AUDIO_FORMAT_NE(U16), - GST_AUDIO_FORMAT_S24_32 = _GST_AUDIO_FORMAT_NE(S24_32), - GST_AUDIO_FORMAT_U24_32 = _GST_AUDIO_FORMAT_NE(U24_32), - GST_AUDIO_FORMAT_S32 = _GST_AUDIO_FORMAT_NE(S32), - GST_AUDIO_FORMAT_U32 = _GST_AUDIO_FORMAT_NE(U32), - GST_AUDIO_FORMAT_S24 = _GST_AUDIO_FORMAT_NE(S24), - GST_AUDIO_FORMAT_U24 = _GST_AUDIO_FORMAT_NE(U24), - GST_AUDIO_FORMAT_S20 = _GST_AUDIO_FORMAT_NE(S20), - GST_AUDIO_FORMAT_U20 = _GST_AUDIO_FORMAT_NE(U20), - GST_AUDIO_FORMAT_S18 = _GST_AUDIO_FORMAT_NE(S18), - GST_AUDIO_FORMAT_U18 = _GST_AUDIO_FORMAT_NE(U18), - GST_AUDIO_FORMAT_F32 = _GST_AUDIO_FORMAT_NE(F32), - GST_AUDIO_FORMAT_F64 = _GST_AUDIO_FORMAT_NE(F64) -} GstAudioFormat; - - -typedef struct _GstAudioFormatInfo GstAudioFormatInfo; -typedef struct _GstAudioInfo GstAudioInfo; - -/** - * GstAudioFormatFlags: - * @GST_AUDIO_FORMAT_FLAG_INTEGER: integer samples - * @GST_AUDIO_FORMAT_FLAG_FLOAT: float samples - * @GST_AUDIO_FORMAT_FLAG_SIGNED: signed samples - * @GST_AUDIO_FORMAT_FLAG_COMPLEX: complex layout - * - * The different audio flags that a format info can have. - */ -typedef enum -{ - GST_AUDIO_FORMAT_FLAG_INTEGER = (1 << 0), - GST_AUDIO_FORMAT_FLAG_FLOAT = (1 << 1), - GST_AUDIO_FORMAT_FLAG_SIGNED = (1 << 2), - GST_AUDIO_FORMAT_FLAG_COMPLEX = (1 << 4) -} GstAudioFormatFlags; - -/** - * GstAudioPackFlags: - * @GST_AUDIO_PACK_FLAG_NONE: No flag - * - * The different flags that can be used when packing and unpacking. - */ -typedef enum -{ - GST_AUDIO_PACK_FLAG_NONE = 0 -} GstAudioPackFlags; - -/** - * GstAudioFormatUnpack: - * @info: a #GstAudioFormatInfo - * @dest: a destination array - * @data: pointer to the audio data - * @length: the amount of samples to unpack. - * - * Unpacks @length samples from the given data of format @info. - * The samples will be unpacked into @dest which each channel - * interleaved. @dest should at least be big enough to hold @length * - * channels * size(unpack_format) bytes. - */ -typedef void (*GstAudioFormatUnpack) (const GstAudioFormatInfo *info, - GstAudioPackFlags flags, gpointer dest, - const gpointer data, gint length); -/** - * GstAudioFormatPack: - * @info: a #GstAudioFormatInfo - * @src: a source array - * @data: pointer to the destination data - * @length: the amount of samples to pack. - * - * Packs @length samples from @src to the data array in format @info. - * The samples from source have each channel interleaved - * and will be packed into @data. - */ -typedef void (*GstAudioFormatPack) (const GstAudioFormatInfo *info, - GstAudioPackFlags flags, const gpointer src, - gpointer data, gint length); - -/** - * GstAudioFormatInfo: - * @format: #GstAudioFormat - * @name: string representation of the format - * @description: user readable description of the format - * @flags: #GstAudioFormatFlags - * @endianness: the endianness - * @width: amount of bits used for one sample - * @depth: amount of valid bits in @width - * @silence: @width/8 bytes with 1 silent sample - * @unpack_format: the format of the unpacked samples - * @unpack_func: function to unpack samples - * @pack_func: function to pack samples - * - * Information for an audio format. - */ -struct _GstAudioFormatInfo { - GstAudioFormat format; - const gchar *name; - const gchar *description; - GstAudioFormatFlags flags; - gint endianness; - gint width; - gint depth; - guint8 silence[8]; - - GstAudioFormat unpack_format; - GstAudioFormatUnpack unpack_func; - GstAudioFormatPack pack_func; - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -GType gst_audio_format_info_get_type (void); - -#define GST_AUDIO_FORMAT_INFO_FORMAT(info) ((info)->format) -#define GST_AUDIO_FORMAT_INFO_NAME(info) ((info)->name) -#define GST_AUDIO_FORMAT_INFO_FLAGS(info) ((info)->flags) - -#define GST_AUDIO_FORMAT_INFO_IS_INTEGER(info) !!((info)->flags & GST_AUDIO_FORMAT_FLAG_INTEGER) -#define GST_AUDIO_FORMAT_INFO_IS_FLOAT(info) !!((info)->flags & GST_AUDIO_FORMAT_FLAG_FLOAT) -#define GST_AUDIO_FORMAT_INFO_IS_SIGNED(info) !!((info)->flags & GST_AUDIO_FORMAT_FLAG_SIGNED) - -#define GST_AUDIO_FORMAT_INFO_ENDIANNESS(info) ((info)->endianness) -#define GST_AUDIO_FORMAT_INFO_IS_LITTLE_ENDIAN(info) ((info)->endianness == G_LITTLE_ENDIAN) -#define GST_AUDIO_FORMAT_INFO_IS_BIG_ENDIAN(info) ((info)->endianness == G_BIG_ENDIAN) -#define GST_AUDIO_FORMAT_INFO_WIDTH(info) ((info)->width) -#define GST_AUDIO_FORMAT_INFO_DEPTH(info) ((info)->depth) - - -GstAudioFormat gst_audio_format_build_integer (gboolean sign, gint endianness, - gint width, gint depth) G_GNUC_CONST; - -GstAudioFormat gst_audio_format_from_string (const gchar *format) G_GNUC_CONST; -const gchar * gst_audio_format_to_string (GstAudioFormat format) G_GNUC_CONST; - -const GstAudioFormatInfo * - gst_audio_format_get_info (GstAudioFormat format) G_GNUC_CONST; - -void gst_audio_format_fill_silence (const GstAudioFormatInfo *info, - gpointer dest, gsize length); - -/** - * GstAudioChannelPosition: - * @GST_AUDIO_CHANNEL_POSITION_MONO: Mono without direction; - * can only be used with 1 channel - * @GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT: Front left - * @GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT: Front right - * @GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER: Front center - * @GST_AUDIO_CHANNEL_POSITION_LFE1: Low-frequency effects 1 (subwoofer) - * @GST_AUDIO_CHANNEL_POSITION_REAR_LEFT: Rear left - * @GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT: Rear right - * @GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: Front left of center - * @GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: Front right of center - * @GST_AUDIO_CHANNEL_POSITION_REAR_CENTER: Rear center - * @GST_AUDIO_CHANNEL_POSITION_LFE2: Low-frequency effects 2 (subwoofer) - * @GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT: Side left - * @GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT: Side right - * @GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT: Top front left - * @GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT: Top front right - * @GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER: Top front center - * @GST_AUDIO_CHANNEL_POSITION_TOP_CENTER: Top center - * @GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT: Top rear left - * @GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT: Top rear right - * @GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT: Top side right - * @GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT: Top rear right - * @GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER: Top rear center - * @GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER: Bottom front center - * @GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT: Bottom front left - * @GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT: Bottom front right - * @GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT: Wide left (between front left and side left) - * @GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT: Wide right (between front right and side right) - * @GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT: Surround left (between rear left and side left) - * @GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT: Surround right (between rear right and side right) - * @GST_AUDIO_CHANNEL_POSITION_NONE: used for position-less channels, e.g. - * from a sound card that records 1024 channels; mutually exclusive with - * any other channel position - * @GST_AUDIO_CHANNEL_POSITION_INVALID: invalid position - * - * Audio channel positions. - * - * These are the channels defined in SMPTE 2036-2-2008 - * Table 1 for 22.2 audio systems with the Surround and Wide channels from - * DTS Coherent Acoustics (v.1.3.1) and 10.2 and 7.1 layouts. In the caps the - * actual channel layout is expressed with a channel count and a channel mask, - * which describes the existing channels. The positions in the bit mask correspond - * to the enum values. - * For negotiation it is allowed to have more bits set in the channel mask than - * the number of channels to specify the allowed channel positions but this is - * not allowed in negotiated caps. It is not allowed in any situation other - * than the one mentioned below to have less bits set in the channel mask than - * the number of channels. - * - * @GST_AUDIO_CHANNEL_POSITION_MONO can only be used with a single mono channel that - * has no direction information and would be mixed into all directional channels. - * This is expressed in caps by having a single channel and no channel mask. - * - * @GST_AUDIO_CHANNEL_POSITION_NONE can only be used if all channels have this position. - * This is expressed in caps by having a channel mask with no bits set. - * - * As another special case it is allowed to have two channels without a channel mask. - * This implicitely means that this is a stereo stream with a front left and front right - * channel. - */ -typedef enum { - /* These get negative indices to allow to use - * the enum values of the normal cases for the - * bit-mask position */ - GST_AUDIO_CHANNEL_POSITION_NONE = -3, - GST_AUDIO_CHANNEL_POSITION_MONO = -2, - GST_AUDIO_CHANNEL_POSITION_INVALID = -1, - - /* Normal cases */ - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT = 0, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE1, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, - GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE2, - GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, - GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT, - GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER, - GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT, - GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT, - GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT -} GstAudioChannelPosition; - -#define GST_AUDIO_CHANNEL_POSITION_MASK(pos) (G_GUINT64_CONSTANT(1)<< GST_AUDIO_CHANNEL_POSITION_ ## pos) - -/** - * GstAudioFlags: - * @GST_AUDIO_FLAG_NONE: no valid flag - * @GST_AUDIO_FLAG_UNPOSITIONED: the position array explicitly - * contains unpositioned channels. - * - * Extra audio flags - */ -typedef enum { - GST_AUDIO_FLAG_NONE = 0, - GST_AUDIO_FLAG_UNPOSITIONED = (1 << 0) -} GstAudioFlags; - -/** - * GstAudioLayout: - * @GST_AUDIO_LAYOUT_INTERLEAVED: interleaved audio - * @GST_AUDIO_LAYOUT_NON_INTERLEAVED: non-interleaved audio - * - * Layout of the audio samples for the different channels. - */ -typedef enum { - GST_AUDIO_LAYOUT_INTERLEAVED = 0, - GST_AUDIO_LAYOUT_NON_INTERLEAVED -} GstAudioLayout; - -/** - * GstAudioInfo: - * @finfo: the format info of the audio - * @flags: additional audio flags - * @layout: audio layout - * @rate: the audio sample rate - * @channels: the number of channels - * @bpf: the number of bytes for one frame, this is the size of one - * sample * @channels - * @position: the positions for each channel - * - * Information describing audio properties. This information can be filled - * in from GstCaps with gst_audio_info_from_caps(). - * - * Use the provided macros to access the info in this structure. - */ -struct _GstAudioInfo { - const GstAudioFormatInfo *finfo; - GstAudioFlags flags; - GstAudioLayout layout; - gint rate; - gint channels; - gint bpf; - GstAudioChannelPosition position[64]; - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING]; -}; - -GType gst_audio_info_get_type (void); - -#define GST_AUDIO_INFO_IS_VALID(i) ((i)->finfo != NULL && (i)->rate > 0 && (i)->channels > 0 && (i)->bpf > 0) - -#define GST_AUDIO_INFO_FORMAT(i) (GST_AUDIO_FORMAT_INFO_FORMAT((i)->finfo)) -#define GST_AUDIO_INFO_NAME(i) (GST_AUDIO_FORMAT_INFO_NAME((i)->finfo)) -#define GST_AUDIO_INFO_WIDTH(i) (GST_AUDIO_FORMAT_INFO_WIDTH((i)->finfo)) -#define GST_AUDIO_INFO_DEPTH(i) (GST_AUDIO_FORMAT_INFO_DEPTH((i)->finfo)) -#define GST_AUDIO_INFO_BPS(info) (GST_AUDIO_INFO_DEPTH(info) >> 3) - -#define GST_AUDIO_INFO_IS_INTEGER(i) (GST_AUDIO_FORMAT_INFO_IS_INTEGER((i)->finfo)) -#define GST_AUDIO_INFO_IS_FLOAT(i) (GST_AUDIO_FORMAT_INFO_IS_FLOAT((i)->finfo)) -#define GST_AUDIO_INFO_IS_SIGNED(i) (GST_AUDIO_FORMAT_INFO_IS_SIGNED((i)->finfo)) - -#define GST_AUDIO_INFO_ENDIANNESS(i) (GST_AUDIO_FORMAT_INFO_ENDIANNES((i)->finfo)) -#define GST_AUDIO_INFO_IS_LITTLE_ENDIAN(i) (GST_AUDIO_FORMAT_INFO_IS_LITTLE_ENDIAN((i)->finfo)) -#define GST_AUDIO_INFO_IS_BIG_ENDIAN(i) (GST_AUDIO_FORMAT_INFO_IS_BIG_ENDIAN((i)->finfo)) - -#define GST_AUDIO_INFO_FLAGS(info) ((info)->flags) -#define GST_AUDIO_INFO_IS_UNPOSITIONED(info) ((info)->flags & GST_AUDIO_FLAG_UNPOSITIONED) -#define GST_AUDIO_INFO_LAYOUT(info) ((info)->layout) - -#define GST_AUDIO_INFO_RATE(info) ((info)->rate) -#define GST_AUDIO_INFO_CHANNELS(info) ((info)->channels) -#define GST_AUDIO_INFO_BPF(info) ((info)->bpf) -#define GST_AUDIO_INFO_POSITION(info,c) ((info)->position[c]) - -GstAudioInfo * gst_audio_info_new (void); -void gst_audio_info_init (GstAudioInfo *info); -GstAudioInfo * gst_audio_info_copy (const GstAudioInfo *info); -void gst_audio_info_free (GstAudioInfo *info); - -void gst_audio_info_set_format (GstAudioInfo *info, GstAudioFormat format, - gint rate, gint channels, - const GstAudioChannelPosition *position); - -gboolean gst_audio_info_from_caps (GstAudioInfo *info, const GstCaps *caps); -GstCaps * gst_audio_info_to_caps (const GstAudioInfo *info); - -gboolean gst_audio_info_convert (const GstAudioInfo * info, - GstFormat src_fmt, gint64 src_val, - GstFormat dest_fmt, gint64 * dest_val); - - - -#define GST_AUDIO_RATE_RANGE "(int) [ 1, max ]" -#define GST_AUDIO_CHANNELS_RANGE "(int) [ 1, max ]" - -#if G_BYTE_ORDER == G_LITTLE_ENDIAN -# define GST_AUDIO_NE(s) G_STRINGIFY(s)"LE" -# define GST_AUDIO_OE(s) G_STRINGIFY(s)"BE" -#else -# define GST_AUDIO_NE(s) G_STRINGIFY(s)"BE" -# define GST_AUDIO_OE(s) G_STRINGIFY(s)"LE" -#endif - -#define GST_AUDIO_FORMATS_ALL " { S8, U8, " \ - "S16LE, S16BE, U16LE, U16BE, " \ - "S24_32LE, S24_32BE, U24_32LE, U24_32BE, " \ - "S32LE, S32BE, U32LE, U32BE, " \ - "S24LE, S24BE, U24LE, U24BE, " \ - "S20LE, S20BE, U20LE, U20BE, " \ - "S18LE, S18BE, U18LE, U18BE, " \ - "F32LE, F32BE, F64LE, F64BE }" - -/** - * GST_AUDIO_CAPS_MAKE: - * @format: string format that describes the pixel layout, as string - * (e.g. "S16LE", "S8", etc.) - * - * Generic caps string for audio, for use in pad templates. - */ -#define GST_AUDIO_CAPS_MAKE(format) \ - "audio/x-raw, " \ - "format = (string) " format ", " \ - "rate = " GST_AUDIO_RATE_RANGE ", " \ - "channels = " GST_AUDIO_CHANNELS_RANGE - -/** - * GST_AUDIO_DEF_RATE: - * - * Standard sampling rate used in consumer audio. - */ -#define GST_AUDIO_DEF_RATE 44100 -/** - * GST_AUDIO_DEF_CHANNELS: - * - * Standard number of channels used in consumer audio. - */ -#define GST_AUDIO_DEF_CHANNELS 2 -/** - * GST_AUDIO_DEF_FORMAT: - * - * Standard format used in consumer audio. - */ -#define GST_AUDIO_DEF_FORMAT "S16LE" +G_BEGIN_DECLS /* conversion macros */ /** @@ -550,35 +60,6 @@ GstBuffer * gst_audio_buffer_clip (GstBuffer *buffer, GstSegment *segment gint rate, gint bpf); -gboolean gst_audio_buffer_reorder_channels (GstBuffer * buffer, - GstAudioFormat format, - gint channels, - const GstAudioChannelPosition * from, - const GstAudioChannelPosition * to); - -gboolean gst_audio_reorder_channels (gpointer data, gsize size, - GstAudioFormat format, - gint channels, - const GstAudioChannelPosition * from, - const GstAudioChannelPosition * to); - -gboolean gst_audio_channel_positions_to_valid_order (GstAudioChannelPosition *position, - gint channels); - -gboolean gst_audio_check_valid_channel_positions (const GstAudioChannelPosition *position, - gint channels, gboolean force_order); - -gboolean gst_audio_channel_positions_to_mask (const GstAudioChannelPosition *position, - gint channels, guint64 *channel_mask); - -gboolean gst_audio_channel_positions_from_mask (gint channels, guint64 channel_mask, - GstAudioChannelPosition * position); - -gboolean gst_audio_get_channel_reorder_map (gint channels, - const GstAudioChannelPosition * from, - const GstAudioChannelPosition * to, - gint *reorder_map); - G_END_DECLS #endif /* __GST_AUDIO_AUDIO_H__ */