f26e0d48c9a36113a14325dc4c774f4acaa2e667
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstaudiometa.c
1 /* GStreamer
2  * Copyright (C) <2011> Wim Taymans <wim.taymans@gmail.com>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <string.h>
21
22 #include "gstaudiometa.h"
23
24 static gboolean
25 gst_audio_downmix_meta_init (GstMeta * meta, gpointer params,
26     GstBuffer * buffer)
27 {
28   GstAudioDownmixMeta *dmeta = (GstAudioDownmixMeta *) meta;
29
30   dmeta->from_position = dmeta->to_position = NULL;
31   dmeta->from_channels = dmeta->to_channels = 0;
32   dmeta->matrix = NULL;
33
34   return TRUE;
35 }
36
37 static void
38 gst_audio_downmix_meta_free (GstMeta * meta, GstBuffer * buffer)
39 {
40   GstAudioDownmixMeta *dmeta = (GstAudioDownmixMeta *) meta;
41
42   g_free (dmeta->from_position);
43   if (dmeta->matrix) {
44     g_free (*dmeta->matrix);
45     g_free (dmeta->matrix);
46   }
47 }
48
49 static gboolean
50 gst_audio_downmix_meta_transform (GstBuffer * dest, GstMeta * meta,
51     GstBuffer * buffer, GQuark type, gpointer data)
52 {
53   GstAudioDownmixMeta *smeta;
54
55   smeta = (GstAudioDownmixMeta *) meta;
56   gst_buffer_add_audio_downmix_meta (dest, smeta->from_position,
57       smeta->from_channels, smeta->to_position, smeta->to_channels,
58       (const gfloat **) smeta->matrix);
59
60   return TRUE;
61 }
62
63 /**
64  * gst_buffer_get_audio_downmix_meta_for_channels:
65  * @buffer: a #GstBuffer
66  * @to_position: (array length=to_channels): the channel positions of
67  *   the destination
68  * @to_channels: The number of channels of the destination
69  *
70  * Find the #GstAudioDownmixMeta on @buffer for the given destination
71  * channel positions.
72  *
73  * Returns: the #GstAudioDownmixMeta on @buffer.
74  */
75 GstAudioDownmixMeta *
76 gst_buffer_get_audio_downmix_meta_for_channels (GstBuffer * buffer,
77     const GstAudioChannelPosition * to_position, gint to_channels)
78 {
79   gpointer state = NULL;
80   GstMeta *meta;
81   const GstMetaInfo *info = GST_AUDIO_DOWNMIX_META_INFO;
82
83   while ((meta = gst_buffer_iterate_meta (buffer, &state))) {
84     if (meta->info->api == info->api) {
85       GstAudioDownmixMeta *ameta = (GstAudioDownmixMeta *) meta;
86       if (ameta->to_channels == to_channels &&
87           memcmp (ameta->to_position, to_position,
88               sizeof (GstAudioChannelPosition) * to_channels) == 0)
89         return ameta;
90     }
91   }
92   return NULL;
93 }
94
95 /**
96  * gst_buffer_add_audio_downmix_meta:
97  * @buffer: a #GstBuffer
98  * @from_position: (array length=from_channels): the channel positions
99  *   of the source
100  * @from_channels: The number of channels of the source
101  * @to_position: (array length=to_channels): the channel positions of
102  *   the destination
103  * @to_channels: The number of channels of the destination
104  * @matrix: The matrix coefficients.
105  *
106  * Attaches GstAudioDownmixMeta metadata to @buffer with the given parameters.
107  *
108  * @matrix is an two-dimensional array of @to_channels times @from_channels
109  * coefficients, i.e. the i-th output channels is constructed by multiplicating
110  * the input channels with the coefficients in @matrix[i] and taking the sum
111  * of the results.
112  *
113  * Returns: the #GstAudioDownmixMeta on @buffer.
114  */
115 GstAudioDownmixMeta *
116 gst_buffer_add_audio_downmix_meta (GstBuffer * buffer,
117     const GstAudioChannelPosition * from_position, gint from_channels,
118     const GstAudioChannelPosition * to_position, gint to_channels,
119     const gfloat ** matrix)
120 {
121   GstAudioDownmixMeta *meta;
122   gint i;
123
124   g_return_val_if_fail (from_position != NULL, NULL);
125   g_return_val_if_fail (from_channels > 0, NULL);
126   g_return_val_if_fail (to_position != NULL, NULL);
127   g_return_val_if_fail (to_channels > 0, NULL);
128   g_return_val_if_fail (matrix != NULL, NULL);
129
130   meta =
131       (GstAudioDownmixMeta *) gst_buffer_add_meta (buffer,
132       GST_AUDIO_DOWNMIX_META_INFO, NULL);
133
134   meta->from_channels = from_channels;
135   meta->to_channels = to_channels;
136
137   meta->from_position =
138       g_new (GstAudioChannelPosition, meta->from_channels + meta->to_channels);
139   meta->to_position = meta->from_position + meta->from_channels;
140   memcpy (meta->from_position, from_position,
141       sizeof (GstAudioChannelPosition) * meta->from_channels);
142   memcpy (meta->to_position, to_position,
143       sizeof (GstAudioChannelPosition) * meta->to_channels);
144
145   meta->matrix = g_new (gfloat *, meta->to_channels);
146   meta->matrix[0] = g_new (gfloat, meta->from_channels * meta->to_channels);
147   memcpy (meta->matrix[0], matrix[0], sizeof (gfloat) * meta->from_channels);
148   for (i = 1; i < meta->to_channels; i++) {
149     meta->matrix[i] = meta->matrix[0] + i * meta->from_channels;
150     memcpy (meta->matrix[i], matrix[i], sizeof (gfloat) * meta->from_channels);
151   }
152
153   return meta;
154 }
155
156 GType
157 gst_audio_downmix_meta_api_get_type (void)
158 {
159   static volatile GType type;
160   static const gchar *tags[] = { NULL };
161
162   if (g_once_init_enter (&type)) {
163     GType _type = gst_meta_api_type_register ("GstAudioDownmixMetaAPI", tags);
164     g_once_init_leave (&type, _type);
165   }
166   return type;
167 }
168
169 const GstMetaInfo *
170 gst_audio_downmix_meta_get_info (void)
171 {
172   static const GstMetaInfo *audio_downmix_meta_info = NULL;
173
174   if (audio_downmix_meta_info == NULL) {
175     audio_downmix_meta_info =
176         gst_meta_register (GST_AUDIO_DOWNMIX_META_API_TYPE,
177         "GstAudioDownmixMeta", sizeof (GstAudioDownmixMeta),
178         gst_audio_downmix_meta_init, gst_audio_downmix_meta_free,
179         gst_audio_downmix_meta_transform);
180   }
181   return audio_downmix_meta_info;
182 }