Blame gst/playback/gstplaybackutils.c

Packit 0652a1
/* Copyright (C) <2014> Intel Corporation
Packit 0652a1
 * Copyright (C) <2014> Sreerenj Balachandran <sreerenj.balachandran@intel.com>
Packit 0652a1
 *
Packit 0652a1
 * Author: Sreerenj Balachandran <sreerenj.balachandran@intel.com>
Packit 0652a1
 *
Packit 0652a1
 * This library is free software; you can redistribute it and/or
Packit 0652a1
 * modify it under the terms of the GNU Library General Public
Packit 0652a1
 * License as published by the Free Software Foundation; either
Packit 0652a1
 * version 2 of the License, or (at your option) any later version.
Packit 0652a1
 *
Packit 0652a1
 * This library is distributed in the hope that it will be useful,
Packit 0652a1
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0652a1
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 0652a1
 * Library General Public License for more details.
Packit 0652a1
 *
Packit 0652a1
 * You should have received a copy of the GNU Library General Public
Packit 0652a1
 * License along with this library; if not, write to the
Packit 0652a1
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 0652a1
 * Boston, MA 02110-1301, USA.
Packit 0652a1
 */
Packit 0652a1
Packit 0652a1
#ifdef HAVE_CONFIG_H
Packit 0652a1
#include "config.h"
Packit 0652a1
#endif
Packit 0652a1
Packit 0652a1
#include <gst/gst.h>
Packit 0652a1
#include "gstplaybackutils.h"
Packit 0652a1
Packit 0652a1
static GstStaticCaps raw_audio_caps = GST_STATIC_CAPS ("audio/x-raw(ANY)");
Packit 0652a1
static GstStaticCaps raw_video_caps = GST_STATIC_CAPS ("video/x-raw(ANY)");
Packit 0652a1
Packit 0652a1
/* unref the caps after usage */
Packit 0652a1
static GstCaps *
Packit 0652a1
get_template_caps (GstElementFactory * factory, GstPadDirection direction)
Packit 0652a1
{
Packit 0652a1
  const GList *templates;
Packit 0652a1
  GstStaticPadTemplate *templ = NULL;
Packit 0652a1
  GList *walk;
Packit 0652a1
Packit 0652a1
  templates = gst_element_factory_get_static_pad_templates (factory);
Packit 0652a1
  for (walk = (GList *) templates; walk; walk = g_list_next (walk)) {
Packit 0652a1
    templ = walk->data;
Packit 0652a1
    if (templ->direction == direction)
Packit 0652a1
      break;
Packit 0652a1
  }
Packit 0652a1
  if (templ)
Packit 0652a1
    return gst_static_caps_get (&templ->static_caps);
Packit 0652a1
  else
Packit 0652a1
    return NULL;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
static gboolean
Packit 0652a1
is_included (GList * list, GstCapsFeatures * cf)
Packit 0652a1
{
Packit 0652a1
  for (; list; list = list->next) {
Packit 0652a1
    if (gst_caps_features_is_equal ((GstCapsFeatures *) list->data, cf))
Packit 0652a1
      return TRUE;
Packit 0652a1
  }
Packit 0652a1
  return FALSE;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
/* compute the number of common caps features */
Packit 0652a1
guint
Packit 0652a1
gst_playback_utils_get_n_common_capsfeatures (GstElementFactory * fact1,
Packit 0652a1
    GstElementFactory * fact2, GstPlayFlags flags, gboolean isaudioelement)
Packit 0652a1
{
Packit 0652a1
  GstCaps *fact1_tmpl_caps, *fact2_tmpl_caps;
Packit 0652a1
  GstCapsFeatures *fact1_features, *fact2_features;
Packit 0652a1
  GstStructure *fact1_struct, *fact2_struct;
Packit 0652a1
  GList *cf_list = NULL;
Packit 0652a1
  guint fact1_caps_size, fact2_caps_size;
Packit 0652a1
  guint i, j, n_common_cf = 0;
Packit 0652a1
  GstCaps *raw_caps =
Packit 0652a1
      (isaudioelement) ? gst_static_caps_get (&raw_audio_caps) :
Packit 0652a1
      gst_static_caps_get (&raw_video_caps);
Packit 0652a1
  GstStructure *raw_struct = gst_caps_get_structure (raw_caps, 0);
Packit 0652a1
  gboolean native_raw =
Packit 0652a1
      (isaudioelement ? ! !(flags & GST_PLAY_FLAG_NATIVE_AUDIO) : ! !(flags &
Packit 0652a1
          GST_PLAY_FLAG_NATIVE_VIDEO));
Packit 0652a1
Packit 0652a1
  fact1_tmpl_caps = get_template_caps (fact1, GST_PAD_SRC);
Packit 0652a1
  fact2_tmpl_caps = get_template_caps (fact2, GST_PAD_SINK);
Packit 0652a1
  if (!fact1_tmpl_caps || !fact2_tmpl_caps) {
Packit 0652a1
    GST_ERROR ("Failed to get template caps from decoder or sink");
Packit 0652a1
    if (fact1_tmpl_caps)
Packit 0652a1
      gst_caps_unref (fact1_tmpl_caps);
Packit 0652a1
    else if (fact2_tmpl_caps)
Packit 0652a1
      gst_caps_unref (fact2_tmpl_caps);
Packit 0652a1
    return 0;
Packit 0652a1
  }
Packit 0652a1
Packit 0652a1
  fact1_caps_size = gst_caps_get_size (fact1_tmpl_caps);
Packit 0652a1
  fact2_caps_size = gst_caps_get_size (fact2_tmpl_caps);
Packit 0652a1
Packit 0652a1
  for (i = 0; i < fact1_caps_size; i++) {
Packit 0652a1
    fact1_features =
Packit 0652a1
        gst_caps_get_features ((const GstCaps *) fact1_tmpl_caps, i);
Packit 0652a1
    if (gst_caps_features_is_any (fact1_features))
Packit 0652a1
      continue;
Packit 0652a1
    fact1_struct =
Packit 0652a1
        gst_caps_get_structure ((const GstCaps *) fact1_tmpl_caps, i);
Packit 0652a1
    for (j = 0; j < fact2_caps_size; j++) {
Packit 0652a1
Packit 0652a1
      fact2_features =
Packit 0652a1
          gst_caps_get_features ((const GstCaps *) fact2_tmpl_caps, j);
Packit 0652a1
      if (gst_caps_features_is_any (fact2_features))
Packit 0652a1
        continue;
Packit 0652a1
      fact2_struct =
Packit 0652a1
          gst_caps_get_structure ((const GstCaps *) fact2_tmpl_caps, j);
Packit 0652a1
Packit 0652a1
      /* A common caps feature is given if the caps features are equal
Packit 0652a1
       * and the structures can intersect. If the NATIVE_AUDIO/NATIVE_VIDEO
Packit 0652a1
       * flags are not set we also allow if both structures are raw caps with
Packit 0652a1
       * system memory caps features, because in that case we have converters in
Packit 0652a1
       * place.
Packit 0652a1
       */
Packit 0652a1
      if (gst_caps_features_is_equal (fact1_features, fact2_features) &&
Packit 0652a1
          (gst_structure_can_intersect (fact1_struct, fact2_struct) ||
Packit 0652a1
              (!native_raw
Packit 0652a1
                  && gst_caps_features_is_equal (fact1_features,
Packit 0652a1
                      GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY)
Packit 0652a1
                  && gst_structure_can_intersect (raw_struct, fact1_struct)
Packit 0652a1
                  && gst_structure_can_intersect (raw_struct, fact2_struct)))
Packit 0652a1
          && !is_included (cf_list, fact2_features)) {
Packit 0652a1
        cf_list = g_list_prepend (cf_list, fact2_features);
Packit 0652a1
        n_common_cf++;
Packit 0652a1
      }
Packit 0652a1
    }
Packit 0652a1
  }
Packit 0652a1
  if (cf_list)
Packit 0652a1
    g_list_free (cf_list);
Packit 0652a1
Packit 0652a1
  gst_caps_unref (fact1_tmpl_caps);
Packit 0652a1
  gst_caps_unref (fact2_tmpl_caps);
Packit 0652a1
Packit 0652a1
  return n_common_cf;
Packit 0652a1
}
Packit 0652a1
Packit 0652a1
gint
Packit 0652a1
gst_playback_utils_compare_factories_func (gconstpointer p1, gconstpointer p2)
Packit 0652a1
{
Packit 0652a1
  GstPluginFeature *f1, *f2;
Packit 0652a1
  gboolean is_parser1, is_parser2;
Packit 0652a1
Packit 0652a1
  f1 = (GstPluginFeature *) p1;
Packit 0652a1
  f2 = (GstPluginFeature *) p2;
Packit 0652a1
Packit 0652a1
  is_parser1 = gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (f1),
Packit 0652a1
      GST_ELEMENT_FACTORY_TYPE_PARSER);
Packit 0652a1
  is_parser2 = gst_element_factory_list_is_type (GST_ELEMENT_FACTORY_CAST (f2),
Packit 0652a1
      GST_ELEMENT_FACTORY_TYPE_PARSER);
Packit 0652a1
Packit 0652a1
Packit 0652a1
  /* We want all parsers first as we always want to plug parsers
Packit 0652a1
   * before decoders */
Packit 0652a1
  if (is_parser1 && !is_parser2)
Packit 0652a1
    return -1;
Packit 0652a1
  else if (!is_parser1 && is_parser2)
Packit 0652a1
    return 1;
Packit 0652a1
Packit 0652a1
  /* And if it's a both a parser we first sort by rank
Packit 0652a1
   * and then by factory name */
Packit 0652a1
  return gst_plugin_feature_rank_compare_func (p1, p2);
Packit 0652a1
}