summaryrefslogtreecommitdiff
path: root/farstream/fs-utils.c
blob: 49955cd92d042332c81467b0cdcf9d741b69462d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
/*
 * Farstream - Miscellaneous useful functions
 *
 * Copyright 2011 Collabora Ltd.
 *  @author: Olivier Crete <olivier.crete@collabora.co.uk>
 * Copyright 2011 Nokia Corp.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA
 */

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "fs-utils.h"

#include <string.h>

#include "fs-rtp.h"

/**
 * SECTION:fs-utils
 * @short_description: Miscellaneous useful functions
 */

static GList *
load_default_codec_preferences_from_path (const gchar *element_name,
    const gchar *path)
{
  GList *codec_prefs = NULL;
  gchar *filename;

  filename = g_build_filename (path, PACKAGE, FS_APIVERSION, element_name,
      "default-codec-preferences", NULL);
  codec_prefs = fs_codec_list_from_keyfile (filename, NULL);
  g_free (filename);

  return codec_prefs;
}

static const gchar *
factory_name_from_element (GstElement *element)
{
  GstElementFactory *factory = gst_element_get_factory (element);

  if (factory)
    return gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory));
  else
    return NULL;
}

/**
 * fs_utils_get_default_codec_preferences:
 * @element: Element for which to fetch default codec preferences
 *
 * These default codec preferences should work with the elements that are
 * available in the main GStreamer element repositories.
 * They should be suitable for standards based protocols like SIP or XMPP.
 *
 * Returns: (element-type FsCodec) (transfer full):
 * The default codec preferences for this plugin.
 * This #GList should be freed with fs_codec_list_destroy()
 */
GList *
fs_utils_get_default_codec_preferences (GstElement *element)
{
  const gchar * const * system_data_dirs = g_get_system_data_dirs ();
  GList *codec_prefs = NULL;
  guint i;
  const gchar *factory_name = factory_name_from_element (element);

  if (!factory_name)
    return NULL;

  codec_prefs = load_default_codec_preferences_from_path (factory_name,
      g_get_user_data_dir ());
  if (codec_prefs)
    return codec_prefs;

  for (i = 0; system_data_dirs[i]; i++)
  {
    codec_prefs = load_default_codec_preferences_from_path (factory_name,
        system_data_dirs[i]);
    if (codec_prefs)
      return codec_prefs;
  }

  return NULL;
}

/**
 * fs_utils_get_default_element_properties: (skip)
 * @element: Element for which to fetch default element properties
 *
 * This function produces a #GKeyFile that can be fed to
 * fs_element_added_notifier_set_properties_from_keyfile(). If no
 * default properties have been found, it will return %NULL.
 *
 * Returns: a #GKeyFile containing the default element
 * properties for this element or %NULL if no properties were found.
 * Caller must free the #GKeyFile when he is done.
 */

GKeyFile *
fs_utils_get_default_element_properties (GstElement *element)
{
  gboolean file_loaded;
  GKeyFile *keyfile = g_key_file_new ();
  gchar *filename;
  const gchar *factory_name = factory_name_from_element (element);

  if (factory_name == NULL)
    return NULL;

  filename = g_build_filename (PACKAGE, FS_APIVERSION, factory_name,
      "default-element-properties", NULL);
  file_loaded = g_key_file_load_from_data_dirs (keyfile, filename, NULL,
      G_KEY_FILE_NONE, NULL);
  g_free (filename);

  if (file_loaded)
  {
    return keyfile;
  }
  else
  {
    g_key_file_free (keyfile);
    return NULL;
  }
}

/**
 * fs_utils_set_bitrate:
 * @element: The #GstElement
 * @bitrate: The bitrate in bits/sec
 *
 * This allows setting the bitrate on all elements that have a "bitrate"
 * property without having to know the type or of the unit used by that element.
 *
 * This will be obsolete in 0.11 (when all elements use bit/sec for the
 * "bitrate" property.
 */

void
fs_utils_set_bitrate (GstElement *element, glong bitrate)
{
  GParamSpec *spec;
  const char *elements_in_kbps[] = { "lamemp3enc", "lame", "x264enc", "twolame",
    "mpeg2enc", NULL
  };
  int i;
  GstElementFactory *factory;
  const gchar *factory_name = NULL;

  g_return_if_fail (GST_IS_ELEMENT (element));

  spec = g_object_class_find_property (G_OBJECT_GET_CLASS (element), "bitrate");
  g_return_if_fail (spec != NULL);

  factory = gst_element_get_factory (element);
  if (factory)
    factory_name = gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory));

  /* divide by 1000 for elements that are known to use kbs */
  for (i = 0; elements_in_kbps[i]; i++)
    if (factory_name && !strcmp (factory_name, elements_in_kbps[i]))
    {
      bitrate /= 1000;
      break;
    }

  if (G_PARAM_SPEC_TYPE (spec) == G_TYPE_LONG)
  {
    g_object_set (element, "bitrate", (glong) CLAMP (bitrate,
            G_PARAM_SPEC_LONG (spec)->minimum,
            G_PARAM_SPEC_LONG (spec)->maximum), NULL);
  }
  else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_ULONG)
  {
    g_object_set (element, "bitrate", (gulong) CLAMP (bitrate,
            G_PARAM_SPEC_ULONG (spec)->minimum,
            G_PARAM_SPEC_ULONG (spec)->maximum), NULL);
  }
  else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_INT)
  {
    gint tmp = MIN (bitrate, G_MAXINT);

    g_object_set (element, "bitrate", (gint)  CLAMP (tmp,
            G_PARAM_SPEC_INT (spec)->minimum,
            G_PARAM_SPEC_INT (spec)->maximum), NULL);
  }
  else if (G_PARAM_SPEC_VALUE_TYPE (spec) == G_TYPE_UINT)
  {
    guint tmp = MIN (bitrate, G_MAXUINT);

    g_object_set (element, "bitrate", (guint) CLAMP (tmp,
            G_PARAM_SPEC_UINT (spec)->minimum,
            G_PARAM_SPEC_UINT (spec)->maximum), NULL);
  }
  else
  {
    g_warning ("bitrate parameter of unknown type");
  }
}

static GList *
load_default_rtp_hdrext_preferences_from_path (const gchar *element_name,
    const gchar *path, FsMediaType media_type)
{
  GList *rtp_hdrext_prefs = NULL;
  gchar *filename;

  filename = g_build_filename (path, PACKAGE, FS_APIVERSION, element_name,
      "default-codec-preferences", NULL);
  rtp_hdrext_prefs = fs_rtp_header_extension_list_from_keyfile (filename,
      media_type, NULL);
  g_free (filename);

  return rtp_hdrext_prefs;
}

/**
 * fs_utils_get_default_rtp_header_extension_preferences:
 * @element: Element for which to fetch default RTP Header Extension preferences
 * @media_type: The #FsMediaType for which to get default RTP Header Extension
 *  preferences
 *
 * These default rtp header extension preferences should work with the elements
 * that are available in the main GStreamer element repositories.
 * They should be suitable for standards based protocols like SIP or XMPP.
 *
 * Returns: (element-type FsCodec) (transfer full): The default rtp
 * header extension preferences for this plugin, this #GList should be
 * freed with fs_codec_list_destroy()
 */
GList *
fs_utils_get_default_rtp_header_extension_preferences (GstElement *element,
    FsMediaType media_type)
{
  const gchar * const * system_data_dirs = g_get_system_data_dirs ();
  GList *rtp_hdrext_prefs = NULL;
  guint i;
  const gchar *factory_name = factory_name_from_element (element);

  if (!factory_name)
    return NULL;

  rtp_hdrext_prefs = load_default_rtp_hdrext_preferences_from_path (
    factory_name, g_get_user_data_dir (), media_type);
  if (rtp_hdrext_prefs)
    return rtp_hdrext_prefs;

  for (i = 0; system_data_dirs[i]; i++)
  {
    rtp_hdrext_prefs = load_default_rtp_hdrext_preferences_from_path (
      factory_name, system_data_dirs[i], media_type);
    if (rtp_hdrext_prefs)
      return rtp_hdrext_prefs;
  }

  return NULL;
}