Blame gst/playback/gstplaybackutils.c

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