static void
kms_muxing_pipeline_configure (KmsMuxingPipeline * self)
{
  GstEncodingContainerProfile *cprof;
  const GList *profiles, *l;
  GstElement *appsrc;

  cprof =
      kms_recording_profile_create_profile (self->priv->profile, TRUE, TRUE);

  profiles = gst_encoding_container_profile_get_profiles (cprof);

  for (l = profiles; l != NULL; l = l->next) {
    GstEncodingProfile *prof = l->data;
    GstCaps *caps;

    if (GST_IS_ENCODING_AUDIO_PROFILE (prof)) {
      appsrc = self->priv->audiosrc;
    } else if (GST_IS_ENCODING_VIDEO_PROFILE (prof)) {
      appsrc = self->priv->videosrc;
    } else
      continue;

    caps = gst_encoding_profile_get_input_caps (prof);

    g_object_set (G_OBJECT (appsrc), "is-live", TRUE, "do-timestamp", FALSE,
        "min-latency", G_GUINT64_CONSTANT (0), "max-latency",
        G_GUINT64_CONSTANT (0), "format", GST_FORMAT_TIME, NULL);

    gst_caps_unref (caps);
  }

  g_object_set (G_OBJECT (self->priv->encodebin), "profile", cprof,
      "audio-jitter-tolerance", 100 * GST_MSECOND,
      "avoid-reencoding", TRUE, NULL);
  gst_encoding_profile_unref (cprof);

  if (self->priv->profile == KMS_RECORDING_PROFILE_MP4) {
    GstElement *mux =
        gst_bin_get_by_name (GST_BIN (self->priv->encodebin), "muxer");

    g_object_set (G_OBJECT (mux), "fragment-duration", 2000, "streamable", TRUE,
        NULL);

    g_object_unref (mux);
  } else if (self->priv->profile == KMS_RECORDING_PROFILE_WEBM) {
    GstElement *mux =
        gst_bin_get_by_name (GST_BIN (self->priv->encodebin), "muxer");

    g_object_set (G_OBJECT (mux), "streamable", TRUE, NULL);

    g_object_unref (mux);
  }
}
/**
 * gst_encoding_profile_get_input_caps:
 * @profile: a #GstEncodingProfile
 *
 * Computes the full output caps that this @profile will be able to consume.
 *
 * Returns: (transfer full): The full caps the given @profile can consume. Call
 * gst_caps_unref() when you are done with the caps.
 */
GstCaps *
gst_encoding_profile_get_input_caps (GstEncodingProfile * profile)
{
  GstCaps *out, *tmp;
  GList *ltmp;
  GstStructure *st, *outst;
  GQuark out_name;
  guint i, len;
  GstCaps *fcaps;

  g_return_val_if_fail (GST_IS_ENCODING_PROFILE (profile), NULL);

  if (GST_IS_ENCODING_CONTAINER_PROFILE (profile)) {
    GstCaps *res = gst_caps_new_empty ();

    for (ltmp = GST_ENCODING_CONTAINER_PROFILE (profile)->encodingprofiles;
        ltmp; ltmp = ltmp->next) {
      GstEncodingProfile *sprof = (GstEncodingProfile *) ltmp->data;
      res = gst_caps_merge (res, gst_encoding_profile_get_input_caps (sprof));
    }
    return res;
  }

  fcaps = profile->format;

  /* fast-path */
  if ((profile->restriction == NULL) || gst_caps_is_any (profile->restriction))
    return gst_caps_ref (fcaps);

  /* Combine the format with the restriction caps */
  outst = gst_caps_get_structure (fcaps, 0);
  out_name = gst_structure_get_name_id (outst);
  tmp = gst_caps_new_empty ();
  len = gst_caps_get_size (profile->restriction);

  for (i = 0; i < len; i++) {
    st = gst_structure_copy (gst_caps_get_structure (profile->restriction, i));
    st->name = out_name;
    gst_caps_append_structure (tmp, st);
  }

  out = gst_caps_intersect (tmp, fcaps);
  gst_caps_unref (tmp);

  return out;
}
static GstCaps *
kms_recorder_endpoint_get_caps_from_profile (KmsRecorderEndpoint * self,
    KmsElementPadType type)
{
  GstEncodingContainerProfile *cprof;
  const GList *profiles, *l;
  GstCaps *caps = NULL;

  switch (type) {
    case KMS_ELEMENT_PAD_TYPE_VIDEO:
      cprof =
          kms_recording_profile_create_profile (self->priv->profile, FALSE,
          TRUE);
      break;
    case KMS_ELEMENT_PAD_TYPE_AUDIO:
      cprof =
          kms_recording_profile_create_profile (self->priv->profile, TRUE,
          FALSE);
      break;
    default:
      return NULL;
  }

  profiles = gst_encoding_container_profile_get_profiles (cprof);

  for (l = profiles; l != NULL; l = l->next) {
    GstEncodingProfile *prof = l->data;

    if ((GST_IS_ENCODING_AUDIO_PROFILE (prof) &&
            type == KMS_ELEMENT_PAD_TYPE_AUDIO) ||
        (GST_IS_ENCODING_VIDEO_PROFILE (prof) &&
            type == KMS_ELEMENT_PAD_TYPE_VIDEO)) {
      caps = gst_encoding_profile_get_input_caps (prof);
      break;
    }
  }

  gst_encoding_profile_unref (cprof);
  return caps;
}
static gboolean
_track_is_compatible_with_profile (GESPipeline * self, GESTrack * track,
    GstEncodingProfile * prof)
{
  if (TRACK_COMPATIBLE_PROFILE (track->type, prof)) {
    if (self->priv->mode == GES_PIPELINE_MODE_SMART_RENDER) {
      GstCaps *ocaps, *rcaps;

      GST_DEBUG ("Smart Render mode, setting input caps");
      ocaps = gst_encoding_profile_get_input_caps (prof);
      ocaps = gst_caps_make_writable (ocaps);
      if (track->type == GES_TRACK_TYPE_AUDIO)
        rcaps = gst_caps_new_empty_simple ("audio/x-raw");
      else
        rcaps = gst_caps_new_empty_simple ("video/x-raw");
      gst_caps_append (ocaps, rcaps);
      ges_track_set_caps (track, ocaps);
      gst_caps_unref (ocaps);
    } else {
      GstCaps *caps = NULL;

      /* Raw preview or rendering mode */
      if (track->type == GES_TRACK_TYPE_VIDEO)
        caps = gst_caps_new_empty_simple ("video/x-raw");
      else if (track->type == GES_TRACK_TYPE_AUDIO)
        caps = gst_caps_new_empty_simple ("audio/x-raw");

      if (caps) {
        ges_track_set_caps (track, caps);
        gst_caps_unref (caps);
      }
    }

    return TRUE;
  }

  return FALSE;
}
static gboolean
ges_timeline_pipeline_update_caps (GESTimelinePipeline * self)
{
  GList *ltrack, *tracks, *lstream;

  if (!self->priv->profile)
    return TRUE;

  GST_DEBUG ("Updating track caps");

  tracks = ges_timeline_get_tracks (self->priv->timeline);

  /* Take each stream of the encoding profile and find a matching
   * track to set the caps on */
  for (ltrack = tracks; ltrack; ltrack = ltrack->next) {
    GESTrack *track = (GESTrack *) ltrack->data;
    GList *allstreams;

    allstreams = (GList *)
        gst_encoding_container_profile_get_profiles (
        (GstEncodingContainerProfile *) self->priv->profile);

    /* Find a matching stream setting */
    for (lstream = allstreams; lstream; lstream = lstream->next) {
      GstEncodingProfile *prof = (GstEncodingProfile *) lstream->data;

      if (TRACK_COMPATIBLE_PROFILE (track->type, prof)) {
        if (self->priv->mode == TIMELINE_MODE_SMART_RENDER) {
          GstCaps *ocaps, *rcaps;

          GST_DEBUG ("Smart Render mode, setting input caps");
          ocaps = gst_encoding_profile_get_input_caps (prof);
          if (track->type == GES_TRACK_TYPE_AUDIO)
            rcaps = gst_caps_from_string ("audio/x-raw-int;audio/x-raw-float");
          else
            rcaps = gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb");
          gst_caps_append (ocaps, rcaps);
          ges_track_set_caps (track, ocaps);
        } else {
          GstCaps *caps = NULL;

          /* Raw preview or rendering mode */
          if (track->type == GES_TRACK_TYPE_VIDEO)
            caps = gst_caps_from_string ("video/x-raw-yuv;video/x-raw-rgb");
          else if (track->type == GES_TRACK_TYPE_AUDIO)
            gst_caps_from_string ("audio/x-raw-int;audio/x-raw-float");

          if (caps) {
            ges_track_set_caps (track, caps);
            gst_caps_unref (caps);
          }
        }
        break;
      }
    }

    g_object_unref (track);
  }

  if (tracks)
    g_list_free (tracks);

  GST_DEBUG ("Done updating caps");

  return TRUE;
}
static void
transcode_file (gchar * uri, gchar * outputuri, GstEncodingProfile * prof)
{
    GstElement *pipeline;
    GstElement *src;
    GstElement *ebin;
    GstElement *sink;
    GstBus *bus;
    GstCaps *profilecaps, *rescaps;
    GMainLoop *mainloop;

    g_print (" Input URI  : %s\n", uri);
    g_print (" Output URI : %s\n", outputuri);

    sink = gst_element_make_from_uri (GST_URI_SINK, outputuri, "sink", NULL);
    if (G_UNLIKELY (sink == NULL)) {
        g_print ("Can't create output sink, most likely invalid output URI !\n");
        return;
    }

    src = gst_element_factory_make ("uridecodebin", NULL);
    if (G_UNLIKELY (src == NULL)) {
        g_print ("Can't create uridecodebin for input URI, aborting!\n");
        return;
    }

    /* Figure out the streams that can be passed as-is to encodebin */
    g_object_get (src, "caps", &rescaps, NULL);
    rescaps = gst_caps_copy (rescaps);
    profilecaps = gst_encoding_profile_get_input_caps (prof);
    gst_caps_append (rescaps, profilecaps);

    /* Set properties */
    g_object_set (src, "uri", uri, "caps", rescaps, NULL);

    ebin = gst_element_factory_make ("encodebin", NULL);
    g_object_set (ebin, "profile", prof, NULL);

    g_signal_connect (src, "autoplug-continue", G_CALLBACK (autoplug_continue_cb),
                      ebin);
    g_signal_connect (src, "pad-added", G_CALLBACK (pad_added_cb), ebin);

    pipeline = gst_pipeline_new ("encoding-pipeline");

    gst_bin_add_many (GST_BIN (pipeline), src, ebin, sink, NULL);

    gst_element_link (ebin, sink);

    mainloop = g_main_loop_new (NULL, FALSE);

    bus = gst_pipeline_get_bus ((GstPipeline *) pipeline);
    gst_bus_add_signal_watch (bus);
    g_signal_connect (bus, "message", G_CALLBACK (bus_message_cb), mainloop);

    if (gst_element_set_state (pipeline,
                               GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) {
        g_print ("Failed to start the encoding\n");
        return;
    }

    g_main_loop_run (mainloop);

    gst_element_set_state (pipeline, GST_STATE_NULL);
    gst_object_unref (pipeline);
}