gst_plugins_base/gst-libs/gst/audio/audio.c
changeset 0 0e761a78d257
child 8 4a7fac7dd34a
equal deleted inserted replaced
-1:000000000000 0:0e761a78d257
       
     1 /* GStreamer
       
     2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
       
     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 #ifdef HAVE_CONFIG_H
       
    21 #  include "config.h"
       
    22 #endif
       
    23 
       
    24 #include "audio.h"
       
    25 #include "multichannel-enumtypes.h"
       
    26 
       
    27 #include <gst/gststructure.h>
       
    28 
       
    29 #ifdef __SYMBIAN32__
       
    30 #include <glib_global.h>
       
    31 #endif
       
    32 
       
    33 /**
       
    34  * SECTION:gstaudio
       
    35  * @short_description: Support library for audio elements
       
    36  *
       
    37  * This library contains some helper functions for audio elements.
       
    38  */
       
    39 
       
    40 /**
       
    41  * gst_audio_frame_byte_size:
       
    42  * @pad: the #GstPad to get the caps from
       
    43  *
       
    44  * Calculate byte size of an audio frame.
       
    45  *
       
    46  * Returns: the byte size, or 0 if there was an error
       
    47  */
       
    48 #ifdef __SYMBIAN32__
       
    49 EXPORT_C
       
    50 #endif
       
    51 
       
    52 int
       
    53 gst_audio_frame_byte_size (GstPad * pad)
       
    54 {
       
    55   /* FIXME: this should be moved closer to the gstreamer core
       
    56    * and be implemented for every mime type IMO
       
    57    */
       
    58 
       
    59   int width = 0;
       
    60   int channels = 0;
       
    61   const GstCaps *caps = NULL;
       
    62   GstStructure *structure;
       
    63 
       
    64   /* get caps of pad */
       
    65   caps = GST_PAD_CAPS (pad);
       
    66 
       
    67   if (caps == NULL) {
       
    68     /* ERROR: could not get caps of pad */
       
    69     g_warning ("gstaudio: could not get caps of pad %s:%s\n",
       
    70         GST_DEBUG_PAD_NAME (pad));
       
    71     return 0;
       
    72   }
       
    73 
       
    74   structure = gst_caps_get_structure (caps, 0);
       
    75 
       
    76   gst_structure_get_int (structure, "width", &width);
       
    77   gst_structure_get_int (structure, "channels", &channels);
       
    78   return (width / 8) * channels;
       
    79 }
       
    80 
       
    81 /**
       
    82  * gst_audio_frame_length:
       
    83  * @pad: the #GstPad to get the caps from
       
    84  * @buf: the #GstBuffer
       
    85  *
       
    86  * Calculate length of buffer in frames.
       
    87  *
       
    88  * Returns: 0 if there's an error, or the number of frames if everything's ok
       
    89  */
       
    90 #ifdef __SYMBIAN32__
       
    91 EXPORT_C
       
    92 #endif
       
    93 
       
    94 long
       
    95 gst_audio_frame_length (GstPad * pad, GstBuffer * buf)
       
    96 {
       
    97   /* FIXME: this should be moved closer to the gstreamer core
       
    98    * and be implemented for every mime type IMO
       
    99    */
       
   100   int frame_byte_size = 0;
       
   101 
       
   102   frame_byte_size = gst_audio_frame_byte_size (pad);
       
   103   if (frame_byte_size == 0)
       
   104     /* error */
       
   105     return 0;
       
   106   /* FIXME: this function assumes the buffer size to be a whole multiple
       
   107    *        of the frame byte size
       
   108    */
       
   109   return GST_BUFFER_SIZE (buf) / frame_byte_size;
       
   110 }
       
   111 
       
   112 /**
       
   113  * gst_audio_duration_from_pad_buffer:
       
   114  * @pad: the #GstPad to get the caps from
       
   115  * @buf: the #GstBuffer
       
   116  *
       
   117  * Calculate length in nanoseconds of audio buffer @buf based on capabilities of
       
   118  * @pad.
       
   119  *
       
   120  * Return: the length.
       
   121  */
       
   122 #ifdef __SYMBIAN32__
       
   123 EXPORT_C
       
   124 #endif
       
   125 
       
   126 GstClockTime
       
   127 gst_audio_duration_from_pad_buffer (GstPad * pad, GstBuffer * buf)
       
   128 {
       
   129   long bytes = 0;
       
   130   int width = 0;
       
   131   int channels = 0;
       
   132   int rate = 0;
       
   133 
       
   134   GstClockTime length;
       
   135 
       
   136   const GstCaps *caps = NULL;
       
   137   GstStructure *structure;
       
   138 
       
   139   g_assert (GST_IS_BUFFER (buf));
       
   140   /* get caps of pad */
       
   141   caps = GST_PAD_CAPS (pad);
       
   142   if (caps == NULL) {
       
   143     /* ERROR: could not get caps of pad */
       
   144     g_warning ("gstaudio: could not get caps of pad %s:%s\n",
       
   145         GST_DEBUG_PAD_NAME (pad));
       
   146     length = GST_CLOCK_TIME_NONE;
       
   147   } else {
       
   148     structure = gst_caps_get_structure (caps, 0);
       
   149     bytes = GST_BUFFER_SIZE (buf);
       
   150     gst_structure_get_int (structure, "width", &width);
       
   151     gst_structure_get_int (structure, "channels", &channels);
       
   152     gst_structure_get_int (structure, "rate", &rate);
       
   153 
       
   154     g_assert (bytes != 0);
       
   155     g_assert (width != 0);
       
   156     g_assert (channels != 0);
       
   157     g_assert (rate != 0);
       
   158     length = (bytes * 8 * GST_SECOND) / (rate * channels * width);
       
   159   }
       
   160   return length;
       
   161 }
       
   162 
       
   163 /**
       
   164  * gst_audio_is_buffer_framed:
       
   165  * @pad: the #GstPad to get the caps from
       
   166  * @buf: the #GstBuffer
       
   167  *
       
   168  * Check if the buffer size is a whole multiple of the frame size.
       
   169  *
       
   170  * Returns: %TRUE if buffer size is multiple.
       
   171  */
       
   172 #ifdef __SYMBIAN32__
       
   173 EXPORT_C
       
   174 #endif
       
   175 
       
   176 gboolean
       
   177 gst_audio_is_buffer_framed (GstPad * pad, GstBuffer * buf)
       
   178 {
       
   179   if (GST_BUFFER_SIZE (buf) % gst_audio_frame_byte_size (pad) == 0)
       
   180     return TRUE;
       
   181   else
       
   182     return FALSE;
       
   183 }
       
   184 
       
   185 /* _getcaps helper functions
       
   186  * sets structure fields to default for audio type
       
   187  * flag determines which structure fields to set to default
       
   188  * keep these functions in sync with the templates in audio.h
       
   189  */
       
   190 
       
   191 /* private helper function
       
   192  * sets a list on the structure
       
   193  * pass in structure, fieldname for the list, type of the list values,
       
   194  * number of list values, and each of the values, terminating with NULL
       
   195  */
       
   196 static void
       
   197 _gst_audio_structure_set_list (GstStructure * structure,
       
   198     const gchar * fieldname, GType type, int number, ...)
       
   199 {
       
   200   va_list varargs;
       
   201   GValue value = { 0 };
       
   202   GArray *array;
       
   203   int j;
       
   204 
       
   205   g_return_if_fail (structure != NULL);
       
   206 
       
   207   g_value_init (&value, GST_TYPE_LIST);
       
   208   array = g_value_peek_pointer (&value);
       
   209 
       
   210   va_start (varargs, number);
       
   211 
       
   212   for (j = 0; j < number; ++j) {
       
   213     int i;
       
   214     gboolean b;
       
   215 
       
   216     GValue list_value = { 0 };
       
   217 
       
   218     switch (type) {
       
   219       case G_TYPE_INT:
       
   220         i = va_arg (varargs, int);
       
   221 
       
   222         g_value_init (&list_value, G_TYPE_INT);
       
   223         g_value_set_int (&list_value, i);
       
   224         break;
       
   225       case G_TYPE_BOOLEAN:
       
   226         b = va_arg (varargs, gboolean);
       
   227         g_value_init (&list_value, G_TYPE_BOOLEAN);
       
   228         g_value_set_boolean (&list_value, b);
       
   229         break;
       
   230       default:
       
   231         g_warning
       
   232             ("_gst_audio_structure_set_list: LIST of given type not implemented.");
       
   233     }
       
   234     g_array_append_val (array, list_value);
       
   235 
       
   236   }
       
   237   gst_structure_set_value (structure, fieldname, &value);
       
   238   va_end (varargs);
       
   239 }
       
   240 
       
   241 /**
       
   242  * gst_audio_structure_set_int:
       
   243  * @structure: a #GstStructure
       
   244  * @flag: a set of #GstAudioFieldFlag
       
   245  *
       
   246  * Do not use anymore.
       
   247  *
       
   248  * Deprecated: use gst_structure_set()
       
   249  */
       
   250 #ifndef GST_REMOVE_DEPRECATED
       
   251 #ifdef GST_DISABLE_DEPRECATED
       
   252 typedef enum
       
   253 {
       
   254   GST_AUDIO_FIELD_RATE = (1 << 0),
       
   255   GST_AUDIO_FIELD_CHANNELS = (1 << 1),
       
   256   GST_AUDIO_FIELD_ENDIANNESS = (1 << 2),
       
   257   GST_AUDIO_FIELD_WIDTH = (1 << 3),
       
   258   GST_AUDIO_FIELD_DEPTH = (1 << 4),
       
   259   GST_AUDIO_FIELD_SIGNED = (1 << 5),
       
   260 } GstAudioFieldFlag;
       
   261 #endif /* GST_DISABLE_DEPRECATED */
       
   262 #ifdef __SYMBIAN32__
       
   263 EXPORT_C
       
   264 #endif
       
   265 
       
   266 
       
   267 void
       
   268 gst_audio_structure_set_int (GstStructure * structure, GstAudioFieldFlag flag)
       
   269 {
       
   270   /* was added here:
       
   271    * http://webcvs.freedesktop.org/gstreamer/gst-plugins-base/gst-libs/gst/audio/audio.c?r1=1.16&r2=1.17
       
   272    * but it is not used
       
   273    */
       
   274   if (flag & GST_AUDIO_FIELD_RATE)
       
   275     gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
       
   276         NULL);
       
   277   if (flag & GST_AUDIO_FIELD_CHANNELS)
       
   278     gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT,
       
   279         NULL);
       
   280   if (flag & GST_AUDIO_FIELD_ENDIANNESS)
       
   281     _gst_audio_structure_set_list (structure, "endianness", G_TYPE_INT, 2,
       
   282         G_LITTLE_ENDIAN, G_BIG_ENDIAN, NULL);
       
   283   if (flag & GST_AUDIO_FIELD_WIDTH)
       
   284     _gst_audio_structure_set_list (structure, "width", G_TYPE_INT, 3, 8, 16, 32,
       
   285         NULL);
       
   286   if (flag & GST_AUDIO_FIELD_DEPTH)
       
   287     gst_structure_set (structure, "depth", GST_TYPE_INT_RANGE, 1, 32, NULL);
       
   288   if (flag & GST_AUDIO_FIELD_SIGNED)
       
   289     _gst_audio_structure_set_list (structure, "signed", G_TYPE_BOOLEAN, 2, TRUE,
       
   290         FALSE, NULL);
       
   291 }
       
   292 #endif /* GST_REMOVE_DEPRECATED */
       
   293 
       
   294 /**
       
   295  * gst_audio_buffer_clip:
       
   296  * @buffer: The buffer to clip.
       
   297  * @segment: Segment in %GST_FORMAT_TIME or %GST_FORMAT_DEFAULT to which the buffer should be clipped.
       
   298  * @rate: sample rate.
       
   299  * @frame_size: size of one audio frame in bytes.
       
   300  *
       
   301  * Clip the the buffer to the given %GstSegment.
       
   302  *
       
   303  * After calling this function the caller does not own a reference to 
       
   304  * @buffer anymore.
       
   305  *
       
   306  * Returns: %NULL if the buffer is completely outside the configured segment,
       
   307  * otherwise the clipped buffer is returned.
       
   308  *
       
   309  * If the buffer has no timestamp, it is assumed to be inside the segment and
       
   310  * is not clipped 
       
   311  *
       
   312  * Since: 0.10.14
       
   313  */
       
   314 #ifdef __SYMBIAN32__
       
   315 EXPORT_C
       
   316 #endif
       
   317 
       
   318 GstBuffer *
       
   319 gst_audio_buffer_clip (GstBuffer * buffer, GstSegment * segment, gint rate,
       
   320     gint frame_size)
       
   321 {
       
   322   GstBuffer *ret;
       
   323   GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
       
   324   guint64 offset = GST_BUFFER_OFFSET_NONE, offset_end = GST_BUFFER_OFFSET_NONE;
       
   325   guint8 *data;
       
   326   guint size;
       
   327 
       
   328   gboolean change_duration = TRUE, change_offset = TRUE, change_offset_end =
       
   329       TRUE;
       
   330 
       
   331   g_return_val_if_fail (segment->format == GST_FORMAT_TIME ||
       
   332       segment->format == GST_FORMAT_DEFAULT, buffer);
       
   333   g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
       
   334 
       
   335   if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
       
   336     /* No timestamp - assume the buffer is completely in the segment */
       
   337     return buffer;
       
   338 
       
   339   /* Get copies of the buffer metadata to change later. 
       
   340    * Calculate the missing values for the calculations,
       
   341    * they won't be changed later though. */
       
   342 
       
   343   data = GST_BUFFER_DATA (buffer);
       
   344   size = GST_BUFFER_SIZE (buffer);
       
   345 
       
   346   timestamp = GST_BUFFER_TIMESTAMP (buffer);
       
   347   if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
       
   348     duration = GST_BUFFER_DURATION (buffer);
       
   349   } else {
       
   350     change_duration = FALSE;
       
   351     duration = gst_util_uint64_scale (size / frame_size, GST_SECOND, rate);
       
   352   }
       
   353 
       
   354   if (GST_BUFFER_OFFSET_IS_VALID (buffer)) {
       
   355     offset = GST_BUFFER_OFFSET (buffer);
       
   356   } else {
       
   357     change_offset = FALSE;
       
   358     offset = 0;
       
   359   }
       
   360 
       
   361   if (GST_BUFFER_OFFSET_END_IS_VALID (buffer)) {
       
   362     offset_end = GST_BUFFER_OFFSET_END (buffer);
       
   363   } else {
       
   364     change_offset_end = FALSE;
       
   365     offset_end = offset + size / frame_size;
       
   366   }
       
   367 
       
   368   if (segment->format == GST_FORMAT_TIME) {
       
   369     /* Handle clipping for GST_FORMAT_TIME */
       
   370 
       
   371     gint64 start, stop, cstart, cstop, diff;
       
   372 
       
   373     start = timestamp;
       
   374     stop = timestamp + duration;
       
   375 
       
   376     if (gst_segment_clip (segment, GST_FORMAT_TIME,
       
   377             start, stop, &cstart, &cstop)) {
       
   378 
       
   379       diff = cstart - start;
       
   380       if (diff > 0) {
       
   381         timestamp = cstart;
       
   382 
       
   383         if (change_duration)
       
   384           duration -= diff;
       
   385 
       
   386         diff = gst_util_uint64_scale (diff, rate, GST_SECOND);
       
   387         if (change_offset)
       
   388           offset += diff;
       
   389         data += diff * frame_size;
       
   390         size -= diff * frame_size;
       
   391       }
       
   392 
       
   393       diff = stop - cstop;
       
   394       if (diff > 0) {
       
   395         /* duration is always valid if stop is valid */
       
   396         duration -= diff;
       
   397 
       
   398         diff = gst_util_uint64_scale (diff, rate, GST_SECOND);
       
   399         if (change_offset_end)
       
   400           offset_end -= diff;
       
   401         size -= diff * frame_size;
       
   402       }
       
   403     } else {
       
   404       gst_buffer_unref (buffer);
       
   405       return NULL;
       
   406     }
       
   407   } else {
       
   408     /* Handle clipping for GST_FORMAT_DEFAULT */
       
   409     gint64 start, stop, cstart, cstop, diff;
       
   410 
       
   411     g_return_val_if_fail (GST_BUFFER_OFFSET_IS_VALID (buffer), buffer);
       
   412 
       
   413     start = offset;
       
   414     stop = offset_end;
       
   415 
       
   416     if (gst_segment_clip (segment, GST_FORMAT_DEFAULT,
       
   417             start, stop, &cstart, &cstop)) {
       
   418 
       
   419       diff = cstart - start;
       
   420       if (diff > 0) {
       
   421         offset = cstart;
       
   422 
       
   423         timestamp = gst_util_uint64_scale (cstart, GST_SECOND, rate);
       
   424 
       
   425         if (change_duration)
       
   426           duration -= gst_util_uint64_scale (diff, GST_SECOND, rate);
       
   427 
       
   428         data += diff * frame_size;
       
   429         size -= diff * frame_size;
       
   430       }
       
   431 
       
   432       diff = stop - cstop;
       
   433       if (diff > 0) {
       
   434         offset_end = cstop;
       
   435 
       
   436         if (change_duration)
       
   437           duration -= gst_util_uint64_scale (diff, GST_SECOND, rate);
       
   438 
       
   439         size -= diff * frame_size;
       
   440       }
       
   441     } else {
       
   442       gst_buffer_unref (buffer);
       
   443       return NULL;
       
   444     }
       
   445   }
       
   446 
       
   447   /* Get a metadata writable buffer and apply all changes */
       
   448   ret = gst_buffer_make_metadata_writable (buffer);
       
   449 
       
   450   GST_BUFFER_TIMESTAMP (ret) = timestamp;
       
   451   GST_BUFFER_SIZE (ret) = size;
       
   452   GST_BUFFER_DATA (ret) = data;
       
   453 
       
   454   if (change_duration)
       
   455     GST_BUFFER_DURATION (ret) = duration;
       
   456   if (change_offset)
       
   457     GST_BUFFER_OFFSET (ret) = offset;
       
   458   if (change_offset_end)
       
   459     GST_BUFFER_OFFSET_END (ret) = offset_end;
       
   460 
       
   461   return ret;
       
   462 }