2 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
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.
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.
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.
21 * @short_description: Support library for audio elements
23 * This library contains some helper functions for audio elements.
31 #include "audio-enumtypes.h"
33 #include <gst/gststructure.h>
38 * gst_audio_frame_byte_size:
39 * @pad: the #GstPad to get the caps from
41 * Calculate byte size of an audio frame.
43 * Returns: the byte size, or 0 if there was an error
46 gst_audio_frame_byte_size (GstPad * pad)
48 /* FIXME: this should be moved closer to the gstreamer core
49 * and be implemented for every mime type IMO
54 const GstCaps *caps = NULL;
55 GstStructure *structure;
58 caps = GST_PAD_CAPS (pad);
61 /* ERROR: could not get caps of pad */
62 g_warning ("gstaudio: could not get caps of pad %s:%s\n",
63 GST_DEBUG_PAD_NAME (pad));
67 structure = gst_caps_get_structure (caps, 0);
69 gst_structure_get_int (structure, "width", &width);
70 gst_structure_get_int (structure, "channels", &channels);
71 return (width / 8) * channels;
75 * gst_audio_frame_length:
76 * @pad: the #GstPad to get the caps from
77 * @buf: the #GstBuffer
79 * Calculate length of buffer in frames.
81 * Returns: 0 if there's an error, or the number of frames if everything's ok
84 gst_audio_frame_length (GstPad * pad, GstBuffer * buf)
86 /* FIXME: this should be moved closer to the gstreamer core
87 * and be implemented for every mime type IMO
89 int frame_byte_size = 0;
91 frame_byte_size = gst_audio_frame_byte_size (pad);
92 if (frame_byte_size == 0)
95 /* FIXME: this function assumes the buffer size to be a whole multiple
96 * of the frame byte size
98 return GST_BUFFER_SIZE (buf) / frame_byte_size;
102 * gst_audio_duration_from_pad_buffer:
103 * @pad: the #GstPad to get the caps from
104 * @buf: the #GstBuffer
106 * Calculate length in nanoseconds of audio buffer @buf based on capabilities of
109 * Returns: the length.
112 gst_audio_duration_from_pad_buffer (GstPad * pad, GstBuffer * buf)
121 const GstCaps *caps = NULL;
122 GstStructure *structure;
124 g_assert (GST_IS_BUFFER (buf));
125 /* get caps of pad */
126 caps = GST_PAD_CAPS (pad);
128 /* ERROR: could not get caps of pad */
129 g_warning ("gstaudio: could not get caps of pad %s:%s\n",
130 GST_DEBUG_PAD_NAME (pad));
131 length = GST_CLOCK_TIME_NONE;
133 structure = gst_caps_get_structure (caps, 0);
134 bytes = GST_BUFFER_SIZE (buf);
135 gst_structure_get_int (structure, "width", &width);
136 gst_structure_get_int (structure, "channels", &channels);
137 gst_structure_get_int (structure, "rate", &rate);
139 g_assert (bytes != 0);
140 g_assert (width != 0);
141 g_assert (channels != 0);
142 g_assert (rate != 0);
143 length = (bytes * 8 * GST_SECOND) / (rate * channels * width);
149 * gst_audio_is_buffer_framed:
150 * @pad: the #GstPad to get the caps from
151 * @buf: the #GstBuffer
153 * Check if the buffer size is a whole multiple of the frame size.
155 * Returns: %TRUE if buffer size is multiple.
158 gst_audio_is_buffer_framed (GstPad * pad, GstBuffer * buf)
160 if (GST_BUFFER_SIZE (buf) % gst_audio_frame_byte_size (pad) == 0)
166 /* _getcaps helper functions
167 * sets structure fields to default for audio type
168 * flag determines which structure fields to set to default
169 * keep these functions in sync with the templates in audio.h
172 /* private helper function
173 * sets a list on the structure
174 * pass in structure, fieldname for the list, type of the list values,
175 * number of list values, and each of the values, terminating with NULL
178 _gst_audio_structure_set_list (GstStructure * structure,
179 const gchar * fieldname, GType type, int number, ...)
182 GValue value = { 0 };
186 g_return_if_fail (structure != NULL);
188 g_value_init (&value, GST_TYPE_LIST);
189 array = g_value_peek_pointer (&value);
191 va_start (varargs, number);
193 for (j = 0; j < number; ++j) {
197 GValue list_value = { 0 };
201 i = va_arg (varargs, int);
203 g_value_init (&list_value, G_TYPE_INT);
204 g_value_set_int (&list_value, i);
207 b = va_arg (varargs, gboolean);
208 g_value_init (&list_value, G_TYPE_BOOLEAN);
209 g_value_set_boolean (&list_value, b);
213 ("_gst_audio_structure_set_list: LIST of given type not implemented.");
215 g_array_append_val (array, list_value);
218 gst_structure_set_value (structure, fieldname, &value);
223 * gst_audio_structure_set_int:
224 * @structure: a #GstStructure
225 * @flag: a set of #GstAudioFieldFlag
227 * Do not use anymore.
229 * Deprecated: use gst_structure_set()
231 #ifndef GST_REMOVE_DEPRECATED
232 #ifdef GST_DISABLE_DEPRECATED
235 GST_AUDIO_FIELD_RATE = (1 << 0),
236 GST_AUDIO_FIELD_CHANNELS = (1 << 1),
237 GST_AUDIO_FIELD_ENDIANNESS = (1 << 2),
238 GST_AUDIO_FIELD_WIDTH = (1 << 3),
239 GST_AUDIO_FIELD_DEPTH = (1 << 4),
240 GST_AUDIO_FIELD_SIGNED = (1 << 5),
243 gst_audio_structure_set_int (GstStructure * structure, GstAudioFieldFlag flag);
244 #endif /* GST_DISABLE_DEPRECATED */
247 gst_audio_structure_set_int (GstStructure * structure, GstAudioFieldFlag flag)
250 * http://webcvs.freedesktop.org/gstreamer/gst-plugins-base/gst-libs/gst/audio/audio.c?r1=1.16&r2=1.17
253 if (flag & GST_AUDIO_FIELD_RATE)
254 gst_structure_set (structure, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT,
256 if (flag & GST_AUDIO_FIELD_CHANNELS)
257 gst_structure_set (structure, "channels", GST_TYPE_INT_RANGE, 1, G_MAXINT,
259 if (flag & GST_AUDIO_FIELD_ENDIANNESS)
260 _gst_audio_structure_set_list (structure, "endianness", G_TYPE_INT, 2,
261 G_LITTLE_ENDIAN, G_BIG_ENDIAN, NULL);
262 if (flag & GST_AUDIO_FIELD_WIDTH)
263 _gst_audio_structure_set_list (structure, "width", G_TYPE_INT, 3, 8, 16, 32,
265 if (flag & GST_AUDIO_FIELD_DEPTH)
266 gst_structure_set (structure, "depth", GST_TYPE_INT_RANGE, 1, 32, NULL);
267 if (flag & GST_AUDIO_FIELD_SIGNED)
268 _gst_audio_structure_set_list (structure, "signed", G_TYPE_BOOLEAN, 2, TRUE,
271 #endif /* GST_REMOVE_DEPRECATED */
273 #define SINT (GST_AUDIO_FORMAT_FLAG_INTEGER | GST_AUDIO_FORMAT_FLAG_SIGNED)
274 #define UINT (GST_AUDIO_FORMAT_FLAG_INTEGER)
276 #define MAKE_FORMAT(str,flags,end,width,depth,silent) \
277 { GST_AUDIO_FORMAT_ ##str, G_STRINGIFY(str), flags, end, width, depth, silent }
279 #define SILENT_0 { 0, 0, 0, 0, 0, 0, 0, 0 }
280 #define SILENT_U8 { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 }
281 #define SILENT_U16LE { 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80 }
282 #define SILENT_U16BE { 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00 }
283 #define SILENT_U24_32LE { 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00 }
284 #define SILENT_U24_32BE { 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00 }
285 #define SILENT_U32LE { 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80 }
286 #define SILENT_U32BE { 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00 }
287 #define SILENT_U24LE { 0x00, 0x00, 0x80, 0x00, 0x00, 0x80 }
288 #define SILENT_U24BE { 0x80, 0x00, 0x00, 0x80, 0x00, 0x00 }
289 #define SILENT_U20LE { 0x00, 0x00, 0x08, 0x00, 0x00, 0x08 }
290 #define SILENT_U20BE { 0x08, 0x00, 0x00, 0x08, 0x00, 0x00 }
291 #define SILENT_U18LE { 0x00, 0x00, 0x02, 0x00, 0x00, 0x02 }
292 #define SILENT_U18BE { 0x02, 0x00, 0x00, 0x02, 0x00, 0x00 }
294 static GstAudioFormatInfo formats[] = {
295 {GST_AUDIO_FORMAT_UNKNOWN, "UNKNOWN", 0, 0, 0, 0},
297 MAKE_FORMAT (S8, SINT, 0, 8, 8, SILENT_0),
298 MAKE_FORMAT (U8, UINT, 0, 8, 8, SILENT_U8),
300 MAKE_FORMAT (S16LE, SINT, G_LITTLE_ENDIAN, 16, 16, SILENT_0),
301 MAKE_FORMAT (S16BE, SINT, G_BIG_ENDIAN, 16, 16, SILENT_0),
302 MAKE_FORMAT (U16LE, UINT, G_LITTLE_ENDIAN, 16, 16, SILENT_U16LE),
303 MAKE_FORMAT (U16BE, UINT, G_BIG_ENDIAN, 16, 16, SILENT_U16BE),
304 /* 24 bit in low 3 bytes of 32 bits */
305 MAKE_FORMAT (S24_32LE, SINT, G_LITTLE_ENDIAN, 32, 24, SILENT_0),
306 MAKE_FORMAT (S24_32BE, SINT, G_BIG_ENDIAN, 32, 24, SILENT_0),
307 MAKE_FORMAT (U24_32LE, UINT, G_LITTLE_ENDIAN, 32, 24, SILENT_U24_32LE),
308 MAKE_FORMAT (U24_32BE, UINT, G_BIG_ENDIAN, 32, 24, SILENT_U24_32BE),
310 MAKE_FORMAT (S32LE, SINT, G_LITTLE_ENDIAN, 32, 32, SILENT_0),
311 MAKE_FORMAT (S32BE, SINT, G_BIG_ENDIAN, 32, 32, SILENT_0),
312 MAKE_FORMAT (U32LE, UINT, G_LITTLE_ENDIAN, 32, 32, SILENT_U32LE),
313 MAKE_FORMAT (U32BE, UINT, G_BIG_ENDIAN, 32, 32, SILENT_U32BE),
314 /* 24 bit in 3 bytes */
315 MAKE_FORMAT (S24LE, SINT, G_LITTLE_ENDIAN, 24, 24, SILENT_0),
316 MAKE_FORMAT (S24BE, SINT, G_BIG_ENDIAN, 24, 24, SILENT_0),
317 MAKE_FORMAT (U24LE, UINT, G_LITTLE_ENDIAN, 24, 24, SILENT_U24LE),
318 MAKE_FORMAT (U24BE, UINT, G_BIG_ENDIAN, 24, 24, SILENT_U24BE),
319 /* 20 bit in 3 bytes */
320 MAKE_FORMAT (S20LE, SINT, G_LITTLE_ENDIAN, 24, 20, SILENT_0),
321 MAKE_FORMAT (S20BE, SINT, G_BIG_ENDIAN, 24, 20, SILENT_0),
322 MAKE_FORMAT (U20LE, UINT, G_LITTLE_ENDIAN, 24, 20, SILENT_U20LE),
323 MAKE_FORMAT (U20BE, UINT, G_BIG_ENDIAN, 24, 20, SILENT_U20BE),
324 /* 18 bit in 3 bytes */
325 MAKE_FORMAT (S18LE, SINT, G_LITTLE_ENDIAN, 24, 18, SILENT_0),
326 MAKE_FORMAT (S18BE, SINT, G_BIG_ENDIAN, 24, 18, SILENT_0),
327 MAKE_FORMAT (U18LE, UINT, G_LITTLE_ENDIAN, 24, 18, SILENT_U18LE),
328 MAKE_FORMAT (U18BE, UINT, G_BIG_ENDIAN, 24, 18, SILENT_U18BE),
330 MAKE_FORMAT (F32LE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 32, 32,
332 MAKE_FORMAT (F32BE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 32, 32,
334 MAKE_FORMAT (F64LE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_LITTLE_ENDIAN, 64, 64,
336 MAKE_FORMAT (F64BE, GST_AUDIO_FORMAT_FLAG_FLOAT, G_BIG_ENDIAN, 64, 64,
340 static GstAudioFormat
341 gst_audio_format_from_caps_structure (const GstStructure * s)
343 gint endianness, width, depth;
346 if (gst_structure_has_name (s, "audio/x-raw-int")) {
349 if (!gst_structure_get_boolean (s, "signed", &sign))
350 goto missing_field_signed;
352 if (!gst_structure_get_int (s, "endianness", &endianness))
353 goto missing_field_endianness;
355 if (!gst_structure_get_int (s, "width", &width))
356 goto missing_field_width;
358 if (!gst_structure_get_int (s, "depth", &depth))
359 goto missing_field_depth;
361 for (i = 0; i < G_N_ELEMENTS (formats); i++) {
362 if (GST_AUDIO_FORMAT_INFO_IS_INTEGER (&formats[i]) &&
363 sign == GST_AUDIO_FORMAT_INFO_IS_SIGNED (&formats[i]) &&
364 GST_AUDIO_FORMAT_INFO_ENDIANNESS (&formats[i]) == endianness &&
365 GST_AUDIO_FORMAT_INFO_WIDTH (&formats[i]) == width &&
366 GST_AUDIO_FORMAT_INFO_DEPTH (&formats[i]) == depth) {
367 return GST_AUDIO_FORMAT_INFO_FORMAT (&formats[i]);
370 } else if (gst_structure_has_name (s, "audio/x-raw-float")) {
371 /* fallbacks are for backwards compatibility (is this needed at all?) */
372 if (!gst_structure_get_int (s, "endianness", &endianness)) {
373 GST_WARNING ("float audio caps without endianness %" GST_PTR_FORMAT, s);
374 endianness = G_BYTE_ORDER;
377 if (!gst_structure_get_int (s, "width", &width)) {
378 GST_WARNING ("float audio caps without width %" GST_PTR_FORMAT, s);
382 for (i = 0; i < G_N_ELEMENTS (formats); i++) {
383 if (GST_AUDIO_FORMAT_INFO_IS_FLOAT (&formats[i]) &&
384 GST_AUDIO_FORMAT_INFO_ENDIANNESS (&formats[i]) == endianness &&
385 GST_AUDIO_FORMAT_INFO_WIDTH (&formats[i]) == width) {
386 return GST_AUDIO_FORMAT_INFO_FORMAT (&formats[i]);
392 return GST_AUDIO_FORMAT_UNKNOWN;
394 missing_field_signed:
396 GST_ERROR ("missing 'signed' field in audio caps %" GST_PTR_FORMAT, s);
397 return GST_AUDIO_FORMAT_UNKNOWN;
399 missing_field_endianness:
401 GST_ERROR ("missing 'endianness' field in audio caps %" GST_PTR_FORMAT, s);
402 return GST_AUDIO_FORMAT_UNKNOWN;
406 GST_ERROR ("missing 'depth' field in audio caps %" GST_PTR_FORMAT, s);
407 return GST_AUDIO_FORMAT_UNKNOWN;
411 GST_ERROR ("missing 'width' field in audio caps %" GST_PTR_FORMAT, s);
412 return GST_AUDIO_FORMAT_UNKNOWN;
416 /* FIXME: remove these if we don't actually go for deep alloc positions */
418 gst_audio_info_init (GstAudioInfo * info)
420 memset (info, 0, sizeof (GstAudioInfo));
424 gst_audio_info_clear (GstAudioInfo * info)
426 memset (info, 0, sizeof (GstAudioInfo));
430 gst_audio_info_copy (GstAudioInfo * info)
432 return (GstAudioInfo *) g_slice_copy (sizeof (GstAudioInfo), info);
436 gst_audio_info_free (GstAudioInfo * info)
438 g_slice_free (GstAudioInfo, info);
442 gst_audio_info_set_format (GstAudioInfo * info, GstAudioFormat format,
443 gint rate, gint channels)
445 const GstAudioFormatInfo *finfo;
447 g_return_if_fail (info != NULL);
448 g_return_if_fail (format != GST_AUDIO_FORMAT_UNKNOWN);
450 finfo = &formats[format];
455 info->channels = channels;
456 info->bpf = (finfo->width * channels) / 8;
459 /* from multichannel.c */
460 void priv_gst_audio_info_fill_default_channel_positions (GstAudioInfo * info);
463 * gst_audio_info_from_caps:
464 * @info: a #GstAudioInfo
467 * Parse @caps and update @info.
469 * Returns: TRUE if @caps could be parsed
474 gst_audio_info_from_caps (GstAudioInfo * info, const GstCaps * caps)
477 GstAudioFormat format;
479 const GValue *pos_val_arr, *pos_val_entry;
482 g_return_val_if_fail (info != NULL, FALSE);
483 g_return_val_if_fail (caps != NULL, FALSE);
484 g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
486 GST_DEBUG ("parsing caps %" GST_PTR_FORMAT, caps);
488 str = gst_caps_get_structure (caps, 0);
490 format = gst_audio_format_from_caps_structure (str);
491 if (format == GST_AUDIO_FORMAT_UNKNOWN)
494 if (!gst_structure_get_int (str, "rate", &rate))
496 if (!gst_structure_get_int (str, "channels", &channels))
499 gst_audio_info_set_format (info, format, rate, channels);
501 pos_val_arr = gst_structure_get_value (str, "channel-positions");
503 if (channels <= G_N_ELEMENTS (info->position)) {
504 for (i = 0; i < channels; i++) {
505 pos_val_entry = gst_value_array_get_value (pos_val_arr, i);
506 info->position[i] = g_value_get_enum (pos_val_entry);
509 /* for that many channels, the positions are always NONE */
510 for (i = 0; i < G_N_ELEMENTS (info->position); i++)
511 info->position[i] = GST_AUDIO_CHANNEL_POSITION_NONE;
512 info->flags |= GST_AUDIO_FLAG_DEFAULT_POSITIONS;
515 info->flags |= GST_AUDIO_FLAG_DEFAULT_POSITIONS;
516 priv_gst_audio_info_fill_default_channel_positions (info);
524 GST_ERROR ("unknown format given");
529 GST_ERROR ("no rate property given");
534 GST_ERROR ("no channels property given");
540 * gst_audio_info_to_caps:
541 * @info: a #GstAudioInfo
543 * Convert the values of @info into a #GstCaps.
545 * Returns: (transfer full): the new #GstCaps containing the
551 gst_audio_info_to_caps (GstAudioInfo * info)
555 g_return_val_if_fail (info != NULL, NULL);
556 g_return_val_if_fail (info->finfo != NULL, NULL);
557 g_return_val_if_fail (info->finfo->format != GST_AUDIO_FORMAT_UNKNOWN, NULL);
559 if (GST_AUDIO_FORMAT_INFO_IS_INTEGER (info->finfo)) {
560 caps = gst_caps_new_simple ("audio/x-raw-int",
561 "width", G_TYPE_INT, GST_AUDIO_INFO_WIDTH (info),
562 "depth", G_TYPE_INT, GST_AUDIO_INFO_DEPTH (info),
563 "endianness", G_TYPE_INT,
564 GST_AUDIO_FORMAT_INFO_ENDIANNESS (info->finfo), "signed",
565 G_TYPE_BOOLEAN, GST_AUDIO_FORMAT_INFO_IS_SIGNED (info->finfo), "rate",
566 G_TYPE_INT, GST_AUDIO_INFO_RATE (info), "channels", G_TYPE_INT,
567 GST_AUDIO_INFO_CHANNELS (info), NULL);
568 } else if (GST_AUDIO_FORMAT_INFO_IS_FLOAT (info->finfo)) {
569 caps = gst_caps_new_simple ("audio/x-raw-float",
570 "width", G_TYPE_INT, GST_AUDIO_INFO_WIDTH (info),
571 "endianness", G_TYPE_INT,
572 GST_AUDIO_FORMAT_INFO_ENDIANNESS (info->finfo), "rate", G_TYPE_INT,
573 GST_AUDIO_INFO_RATE (info), "channels", G_TYPE_INT,
574 GST_AUDIO_INFO_CHANNELS (info), NULL);
576 GST_ERROR ("unknown audio format, neither integer nor float");
580 if (info->channels > 2) {
581 GValue pos_val_arr = { 0 }
587 /* build gvaluearray from positions */
588 g_value_init (&pos_val_arr, GST_TYPE_ARRAY);
589 g_value_init (&pos_val_entry, GST_TYPE_AUDIO_CHANNEL_POSITION);
590 for (i = 0; i < info->channels; i++) {
591 /* if we have many many channels, all positions are NONE */
592 if (info->channels <= 64)
593 g_value_set_enum (&pos_val_entry, info->position[i]);
595 g_value_set_enum (&pos_val_entry, GST_AUDIO_CHANNEL_POSITION_NONE);
597 gst_value_array_append_value (&pos_val_arr, &pos_val_entry);
599 g_value_unset (&pos_val_entry);
601 /* add to structure */
602 str = gst_caps_get_structure (caps, 0);
603 gst_structure_set_value (str, "channel-positions", &pos_val_arr);
604 g_value_unset (&pos_val_arr);
611 * gst_audio_format_convert:
612 * @info: a #GstAudioInfo
613 * @src_format: #GstFormat of the @src_value
614 * @src_value: value to convert
615 * @dest_format: #GstFormat of the @dest_value
616 * @dest_value: pointer to destination value
618 * Converts among various #GstFormat types. This function handles
619 * GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For
620 * raw audio, GST_FORMAT_DEFAULT corresponds to audio frames. This
621 * function can be used to handle pad queries of the type GST_QUERY_CONVERT.
623 * Returns: TRUE if the conversion was successful.
628 gst_audio_info_convert (GstAudioInfo * info,
629 GstFormat src_fmt, gint64 src_val, GstFormat dest_fmt, gint64 * dest_val)
634 GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)",
635 src_val, gst_format_get_name (src_fmt), src_fmt,
636 gst_format_get_name (dest_fmt), dest_fmt);
638 if (src_fmt == dest_fmt || src_val == -1) {
643 /* get important info */
644 bpf = GST_AUDIO_INFO_BPF (info);
645 rate = GST_AUDIO_INFO_RATE (info);
647 if (bpf == 0 || rate == 0) {
648 GST_DEBUG ("no rate or bpf configured");
654 case GST_FORMAT_BYTES:
656 case GST_FORMAT_TIME:
657 *dest_val = GST_FRAMES_TO_CLOCK_TIME (src_val / bpf, rate);
659 case GST_FORMAT_DEFAULT:
660 *dest_val = src_val / bpf;
667 case GST_FORMAT_DEFAULT:
669 case GST_FORMAT_TIME:
670 *dest_val = GST_FRAMES_TO_CLOCK_TIME (src_val, rate);
672 case GST_FORMAT_BYTES:
673 *dest_val = src_val * bpf;
680 case GST_FORMAT_TIME:
682 case GST_FORMAT_DEFAULT:
683 *dest_val = GST_CLOCK_TIME_TO_FRAMES (src_val, rate);
685 case GST_FORMAT_BYTES:
686 *dest_val = GST_CLOCK_TIME_TO_FRAMES (src_val, rate);
699 GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, res, *dest_val);
705 * gst_audio_buffer_clip:
706 * @buffer: The buffer to clip.
707 * @segment: Segment in %GST_FORMAT_TIME or %GST_FORMAT_DEFAULT to which the buffer should be clipped.
708 * @rate: sample rate.
709 * @frame_size: size of one audio frame in bytes.
711 * Clip the buffer to the given %GstSegment.
713 * After calling this function the caller does not own a reference to
716 * Returns: %NULL if the buffer is completely outside the configured segment,
717 * otherwise the clipped buffer is returned.
719 * If the buffer has no timestamp, it is assumed to be inside the segment and
725 gst_audio_buffer_clip (GstBuffer * buffer, GstSegment * segment, gint rate,
729 GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
730 guint64 offset = GST_BUFFER_OFFSET_NONE, offset_end = GST_BUFFER_OFFSET_NONE;
734 gboolean change_duration = TRUE, change_offset = TRUE, change_offset_end =
737 g_return_val_if_fail (segment->format == GST_FORMAT_TIME ||
738 segment->format == GST_FORMAT_DEFAULT, buffer);
739 g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
741 if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
742 /* No timestamp - assume the buffer is completely in the segment */
745 /* Get copies of the buffer metadata to change later.
746 * Calculate the missing values for the calculations,
747 * they won't be changed later though. */
749 data = GST_BUFFER_DATA (buffer);
750 size = GST_BUFFER_SIZE (buffer);
752 timestamp = GST_BUFFER_TIMESTAMP (buffer);
753 if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
754 duration = GST_BUFFER_DURATION (buffer);
756 change_duration = FALSE;
757 duration = gst_util_uint64_scale (size / frame_size, GST_SECOND, rate);
760 if (GST_BUFFER_OFFSET_IS_VALID (buffer)) {
761 offset = GST_BUFFER_OFFSET (buffer);
763 change_offset = FALSE;
767 if (GST_BUFFER_OFFSET_END_IS_VALID (buffer)) {
768 offset_end = GST_BUFFER_OFFSET_END (buffer);
770 change_offset_end = FALSE;
771 offset_end = offset + size / frame_size;
774 if (segment->format == GST_FORMAT_TIME) {
775 /* Handle clipping for GST_FORMAT_TIME */
777 gint64 start, stop, cstart, cstop, diff;
780 stop = timestamp + duration;
782 if (gst_segment_clip (segment, GST_FORMAT_TIME,
783 start, stop, &cstart, &cstop)) {
785 diff = cstart - start;
792 diff = gst_util_uint64_scale (diff, rate, GST_SECOND);
795 data += diff * frame_size;
796 size -= diff * frame_size;
801 /* duration is always valid if stop is valid */
804 diff = gst_util_uint64_scale (diff, rate, GST_SECOND);
805 if (change_offset_end)
807 size -= diff * frame_size;
810 gst_buffer_unref (buffer);
814 /* Handle clipping for GST_FORMAT_DEFAULT */
815 gint64 start, stop, cstart, cstop, diff;
817 g_return_val_if_fail (GST_BUFFER_OFFSET_IS_VALID (buffer), buffer);
822 if (gst_segment_clip (segment, GST_FORMAT_DEFAULT,
823 start, stop, &cstart, &cstop)) {
825 diff = cstart - start;
829 timestamp = gst_util_uint64_scale (cstart, GST_SECOND, rate);
832 duration -= gst_util_uint64_scale (diff, GST_SECOND, rate);
834 data += diff * frame_size;
835 size -= diff * frame_size;
843 duration -= gst_util_uint64_scale (diff, GST_SECOND, rate);
845 size -= diff * frame_size;
848 gst_buffer_unref (buffer);
853 /* Get a metadata writable buffer and apply all changes */
854 ret = gst_buffer_make_metadata_writable (buffer);
856 GST_BUFFER_TIMESTAMP (ret) = timestamp;
857 GST_BUFFER_SIZE (ret) = size;
858 GST_BUFFER_DATA (ret) = data;
861 GST_BUFFER_DURATION (ret) = duration;
863 GST_BUFFER_OFFSET (ret) = offset;
864 if (change_offset_end)
865 GST_BUFFER_OFFSET_END (ret) = offset_end;