Blame gst-libs/gst/audio/gstaudioutilsprivate.c

Packit 971217
/* GStreamer
Packit 971217
 * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>.
Packit 971217
 * Copyright (C) 2011 Nokia Corporation. All rights reserved.
Packit 971217
 *   Contact: Stefan Kost <stefan.kost@nokia.com>
Packit 971217
 *
Packit 971217
 * This library is free software; you can redistribute it and/or
Packit 971217
 * modify it under the terms of the GNU Library General Public
Packit 971217
 * License as published by the Free Software Foundation; either
Packit 971217
 * version 2 of the License, or (at your option) any later version.
Packit 971217
 *
Packit 971217
 * This library is distributed in the hope that it will be useful,
Packit 971217
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 971217
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 971217
 * Library General Public License for more details.
Packit 971217
 *
Packit 971217
 * You should have received a copy of the GNU Library General Public
Packit 971217
 * License along with this library; if not, write to the
Packit 971217
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 971217
 * Boston, MA 02110-1301, USA.
Packit 971217
 */
Packit 971217
Packit 971217
#ifdef HAVE_CONFIG_H
Packit 971217
#include "config.h"
Packit 971217
#endif
Packit 971217
Packit 971217
#include <gst/audio/audio.h>
Packit 971217
#include "gstaudioutilsprivate.h"
Packit 971217
Packit 971217
/*
Packit 971217
 * Takes caps and copies its audio fields to tmpl_caps
Packit 971217
 */
Packit 971217
static GstCaps *
Packit 971217
__gst_audio_element_proxy_caps (GstElement * element, GstCaps * templ_caps,
Packit 971217
    GstCaps * caps)
Packit 971217
{
Packit 971217
  GstCaps *result = gst_caps_new_empty ();
Packit 971217
  gint i, j;
Packit 971217
  gint templ_caps_size = gst_caps_get_size (templ_caps);
Packit 971217
  gint caps_size = gst_caps_get_size (caps);
Packit 971217
Packit 971217
  for (i = 0; i < templ_caps_size; i++) {
Packit 971217
    GQuark q_name =
Packit 971217
        gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
Packit 971217
    GstCapsFeatures *features = gst_caps_get_features (templ_caps, i);
Packit 971217
Packit 971217
    for (j = 0; j < caps_size; j++) {
Packit 971217
      const GstStructure *caps_s = gst_caps_get_structure (caps, j);
Packit 971217
      const GValue *val;
Packit 971217
      GstStructure *s;
Packit 971217
      GstCaps *tmp = gst_caps_new_empty ();
Packit 971217
Packit 971217
      s = gst_structure_new_id_empty (q_name);
Packit 971217
      if ((val = gst_structure_get_value (caps_s, "rate")))
Packit 971217
        gst_structure_set_value (s, "rate", val);
Packit 971217
      if ((val = gst_structure_get_value (caps_s, "channels")))
Packit 971217
        gst_structure_set_value (s, "channels", val);
Packit 971217
      if ((val = gst_structure_get_value (caps_s, "channels-mask")))
Packit 971217
        gst_structure_set_value (s, "channels-mask", val);
Packit 971217
Packit 971217
      gst_caps_append_structure_full (tmp, s,
Packit 971217
          gst_caps_features_copy (features));
Packit 971217
      result = gst_caps_merge (result, tmp);
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  return result;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * __gst_audio_element_proxy_getcaps:
Packit 971217
 * @element: a #GstElement
Packit 971217
 * @sinkpad: the element's sink #GstPad
Packit 971217
 * @srcpad: the element's source #GstPad
Packit 971217
 * @initial_caps: initial caps
Packit 971217
 * @filter: filter caps
Packit 971217
 *
Packit 971217
 * Returns caps that express @initial_caps (or sink template caps if
Packit 971217
 * @initial_caps == NULL) restricted to rate/channels/...
Packit 971217
 * combinations supported by downstream elements (e.g. muxers).
Packit 971217
 *
Packit 971217
 * Returns: a #GstCaps owned by caller
Packit 971217
 */
Packit 971217
GstCaps *
Packit 971217
__gst_audio_element_proxy_getcaps (GstElement * element, GstPad * sinkpad,
Packit 971217
    GstPad * srcpad, GstCaps * initial_caps, GstCaps * filter)
Packit 971217
{
Packit 971217
  GstCaps *templ_caps, *src_templ_caps;
Packit 971217
  GstCaps *peer_caps;
Packit 971217
  GstCaps *allowed;
Packit 971217
  GstCaps *fcaps, *filter_caps;
Packit 971217
Packit 971217
  /* Allow downstream to specify rate/channels constraints
Packit 971217
   * and forward them upstream for audio converters to handle
Packit 971217
   */
Packit 971217
  templ_caps = initial_caps ? gst_caps_ref (initial_caps) :
Packit 971217
      gst_pad_get_pad_template_caps (sinkpad);
Packit 971217
  src_templ_caps = gst_pad_get_pad_template_caps (srcpad);
Packit 971217
  if (filter && !gst_caps_is_any (filter)) {
Packit 971217
    GstCaps *proxy_filter =
Packit 971217
        __gst_audio_element_proxy_caps (element, src_templ_caps, filter);
Packit 971217
Packit 971217
    peer_caps = gst_pad_peer_query_caps (srcpad, proxy_filter);
Packit 971217
    gst_caps_unref (proxy_filter);
Packit 971217
  } else {
Packit 971217
    peer_caps = gst_pad_peer_query_caps (srcpad, NULL);
Packit 971217
  }
Packit 971217
Packit 971217
  allowed = gst_caps_intersect_full (peer_caps, src_templ_caps,
Packit 971217
      GST_CAPS_INTERSECT_FIRST);
Packit 971217
Packit 971217
  gst_caps_unref (src_templ_caps);
Packit 971217
  gst_caps_unref (peer_caps);
Packit 971217
Packit 971217
  if (!allowed || gst_caps_is_any (allowed)) {
Packit 971217
    fcaps = templ_caps;
Packit 971217
    goto done;
Packit 971217
  } else if (gst_caps_is_empty (allowed)) {
Packit 971217
    fcaps = gst_caps_ref (allowed);
Packit 971217
    goto done;
Packit 971217
  }
Packit 971217
Packit 971217
  GST_LOG_OBJECT (element, "template caps %" GST_PTR_FORMAT, templ_caps);
Packit 971217
  GST_LOG_OBJECT (element, "allowed caps %" GST_PTR_FORMAT, allowed);
Packit 971217
Packit 971217
  filter_caps = __gst_audio_element_proxy_caps (element, templ_caps, allowed);
Packit 971217
Packit 971217
  fcaps = gst_caps_intersect (filter_caps, templ_caps);
Packit 971217
  gst_caps_unref (filter_caps);
Packit 971217
  gst_caps_unref (templ_caps);
Packit 971217
Packit 971217
  if (filter) {
Packit 971217
    GST_LOG_OBJECT (element, "intersecting with %" GST_PTR_FORMAT, filter);
Packit 971217
    filter_caps = gst_caps_intersect (fcaps, filter);
Packit 971217
    gst_caps_unref (fcaps);
Packit 971217
    fcaps = filter_caps;
Packit 971217
  }
Packit 971217
Packit 971217
done:
Packit 971217
  gst_caps_replace (&allowed, NULL);
Packit 971217
Packit 971217
  GST_LOG_OBJECT (element, "proxy caps %" GST_PTR_FORMAT, fcaps);
Packit 971217
Packit 971217
  return fcaps;
Packit 971217
}
Packit 971217
Packit 971217
/**
Packit 971217
 * __gst_audio_encoded_audio_convert:
Packit 971217
 * @fmt: audio format of the encoded audio
Packit 971217
 * @bytes: number of encoded bytes
Packit 971217
 * @samples: number of encoded samples
Packit 971217
 * @src_format: source format
Packit 971217
 * @src_value: source value
Packit 971217
 * @dest_format: destination format
Packit 971217
 * @dest_value: destination format
Packit 971217
 *
Packit 971217
 * Helper function to convert @src_value in @src_format to @dest_value in
Packit 971217
 * @dest_format for encoded audio data.  Conversion is possible between
Packit 971217
 * BYTE and TIME format by using estimated bitrate based on
Packit 971217
 * @samples and @bytes (and @fmt).
Packit 971217
 */
Packit 971217
gboolean
Packit 971217
__gst_audio_encoded_audio_convert (GstAudioInfo * fmt,
Packit 971217
    gint64 bytes, gint64 samples, GstFormat src_format,
Packit 971217
    gint64 src_value, GstFormat * dest_format, gint64 * dest_value)
Packit 971217
{
Packit 971217
  gboolean res = FALSE;
Packit 971217
Packit 971217
  g_return_val_if_fail (dest_format != NULL, FALSE);
Packit 971217
  g_return_val_if_fail (dest_value != NULL, FALSE);
Packit 971217
Packit 971217
  if (G_UNLIKELY (src_format == *dest_format || src_value == 0 ||
Packit 971217
          src_value == -1)) {
Packit 971217
    if (dest_value)
Packit 971217
      *dest_value = src_value;
Packit 971217
    return TRUE;
Packit 971217
  }
Packit 971217
Packit 971217
  if (samples == 0 || bytes == 0 || fmt->rate == 0) {
Packit 971217
    GST_DEBUG ("not enough metadata yet to convert");
Packit 971217
    goto exit;
Packit 971217
  }
Packit 971217
Packit 971217
  bytes *= fmt->rate;
Packit 971217
Packit 971217
  switch (src_format) {
Packit 971217
    case GST_FORMAT_BYTES:
Packit 971217
      switch (*dest_format) {
Packit 971217
        case GST_FORMAT_TIME:
Packit 971217
          *dest_value = gst_util_uint64_scale (src_value,
Packit 971217
              GST_SECOND * samples, bytes);
Packit 971217
          res = TRUE;
Packit 971217
          break;
Packit 971217
        default:
Packit 971217
          res = FALSE;
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    case GST_FORMAT_TIME:
Packit 971217
      switch (*dest_format) {
Packit 971217
        case GST_FORMAT_BYTES:
Packit 971217
          *dest_value = gst_util_uint64_scale (src_value, bytes,
Packit 971217
              samples * GST_SECOND);
Packit 971217
          res = TRUE;
Packit 971217
          break;
Packit 971217
        default:
Packit 971217
          res = FALSE;
Packit 971217
      }
Packit 971217
      break;
Packit 971217
    default:
Packit 971217
      res = FALSE;
Packit 971217
  }
Packit 971217
Packit 971217
exit:
Packit 971217
  return res;
Packit 971217
}