コード例 #1
0
static void
kms_recorder_endpoint_started (KmsUriEndpoint * obj)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);

  kms_recorder_endpoint_change_state (self);

  /* Set internal pipeline to playing */
  gst_element_set_state (self->priv->pipeline, GST_STATE_PLAYING);

  KMS_ELEMENT_LOCK (self);

  if (GST_CLOCK_TIME_IS_VALID (self->priv->paused_start)) {
    self->priv->paused_time +=
        gst_clock_get_time (GST_ELEMENT (self->priv->pipeline)->clock) -
        self->priv->paused_start;
    self->priv->paused_start = GST_CLOCK_TIME_NONE;
  }

  KMS_ELEMENT_UNLOCK (self);

  /* Open valves */
  kms_recorder_endpoint_open_valves (self);

  kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_START);
}
コード例 #2
0
static void
kms_recorder_endpoint_started (KmsUriEndpoint * obj)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);

  kms_recorder_endpoint_create_parent_directories (self);

  kms_recorder_endpoint_change_state (self);

  /* Set internal pipeline to playing */
  kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PLAYING);

  BASE_TIME_LOCK (self);

  if (GST_CLOCK_TIME_IS_VALID (self->priv->paused_start)) {
    self->priv->paused_time +=
        gst_clock_get_time (kms_base_media_muxer_get_clock (self->priv->mux)) -
        self->priv->paused_start;
    self->priv->paused_start = GST_CLOCK_TIME_NONE;
  }

  BASE_TIME_UNLOCK (self);

  kms_recorder_generate_pads (self);

  kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_START);
}
コード例 #3
0
static void
kms_recorder_endpoint_dispose (GObject * object)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  GST_DEBUG_OBJECT (self, "dispose");

  g_clear_object (&self->priv->loop);
  g_clear_object (&self->priv->controller);

  if (self->priv->pipeline != NULL) {
    if (GST_STATE (self->priv->pipeline) != GST_STATE_NULL) {
      GST_ELEMENT_WARNING (self, RESOURCE, BUSY,
          ("Recorder may have buffers to save"),
          ("Disposing recorder when it isn't stopped."));
    }
    gst_element_set_state (self->priv->pipeline, GST_STATE_NULL);
    g_object_unref (self->priv->pipeline);
    self->priv->pipeline = NULL;
  }

  /* clean up as possible.  may be called multiple times */

  G_OBJECT_CLASS (kms_recorder_endpoint_parent_class)->dispose (object);
}
コード例 #4
0
static void
kms_recorder_endpoint_paused (KmsUriEndpoint * obj)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);
  GstClock *clk;

  kms_recorder_endpoint_change_state (self, KMS_URI_ENDPOINT_STATE_PAUSE);

  kms_recorder_endpoint_remove_pads (self);

  KMS_ELEMENT_UNLOCK (self);

  /* Set internal pipeline to GST_STATE_PAUSED */
  kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_PAUSED);

  KMS_ELEMENT_LOCK (self);

  clk = kms_base_media_muxer_get_clock (self->priv->mux);

  if (clk) {
    self->priv->paused_start = gst_clock_get_time (clk);
  }

  kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_PAUSE);
}
コード例 #5
0
static void
kms_recorder_endpoint_audio_valve_added (KmsElement * self, GstElement * valve)
{
  // TODO: This caps should be set using the profile data
  kms_recorder_endpoint_valve_added (KMS_RECORDER_ENDPOINT (self), valve,
      AUDIO_APPSINK, AUDIO_APPSRC, "audio_%u");
}
コード例 #6
0
static void
sink_required_cb (KmsConfController * controller, gpointer recorder)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (recorder);
  gulong *probe_id;
  GstElement *sink;
  GstPad *sinkpad;

  sink = kms_recorder_endpoint_get_sink (self);

  if (sink == NULL) {
    sink = gst_element_factory_make ("fakesink", NULL);
    GST_ELEMENT_ERROR (self, STREAM, WRONG_TYPE, ("No available sink"), (NULL));
    return;
  }

  g_object_set (self->priv->controller, "sink", sink, NULL);

  sinkpad = gst_element_get_static_pad (sink, "sink");
  if (sinkpad == NULL) {
    GST_WARNING ("No sink pad available for element %" GST_PTR_FORMAT, sink);
    return;
  }

  probe_id = g_slice_new0 (gulong);
  *probe_id = gst_pad_add_probe (sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM,
      stop_notification_cb, self, NULL);
  g_object_set_data_full (G_OBJECT (sinkpad), KEY_RECORDER_PAD_PROBE_ID,
      probe_id, destroy_ulong);
  g_object_unref (sinkpad);
}
コード例 #7
0
static void
kms_recorder_endpoint_on_eos_message (gpointer data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (data);

  kms_recorder_endpoint_on_eos (self->priv->mux, self);
}
コード例 #8
0
static void
kms_recorder_endpoint_set_property (GObject * object, guint property_id,
    const GValue * value, GParamSpec * pspec)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));
  switch (property_id) {
    case PROP_DVR:
      self->priv->use_dvr = g_value_get_boolean (value);
      break;
    case PROP_PROFILE:{
      if (self->priv->profile == KMS_RECORDING_PROFILE_NONE) {
        self->priv->profile = g_value_get_enum (value);

        if (self->priv->profile != KMS_RECORDING_PROFILE_NONE) {
          kms_recorder_endpoint_new_media_muxer (self);
        }
      } else {
        GST_ERROR_OBJECT (self, "Profile can only be configured once");
      }

      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));
}
コード例 #9
0
static void
unlink_sinkpad_cb (GstPad * pad, GstPad * peer, gpointer user_data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (user_data);
  gchar *id = NULL;

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));

  id = gst_pad_get_name (pad);

  if (self->priv->stopping) {
    GST_DEBUG_OBJECT (self, "Stop operation is pending");
    self->priv->pending_pads = g_slist_prepend (self->priv->pending_pads,
        g_strdup (id));
    goto end;
  }

  if (kms_base_media_muxer_remove_src (self->priv->mux, id)) {
    g_hash_table_remove (self->priv->srcs, id);
  }

end:
  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));

  g_free (id);
}
コード例 #10
0
static void
kms_recorder_endpoint_dispose (GObject * object)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  GST_DEBUG_OBJECT (self, "dispose");

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));

  if (self->priv->mux != NULL) {
    if (kms_base_media_muxer_get_state (self->priv->mux) != GST_STATE_NULL) {
      GST_ELEMENT_WARNING (self, RESOURCE, BUSY,
          ("Recorder may have buffers to save"),
          ("Disposing recorder when it isn't stopped."));
    }

    kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL);

    if (self->priv->stopping) {
      GST_WARNING_OBJECT (self, "Forcing pending stop operation to finish");
      kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP);
      self->priv->stopping = FALSE;
    }
  }

  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));

  g_mutex_clear (&self->priv->base_time_lock);

  /* clean up as possible.  may be called multiple times */

  G_OBJECT_CLASS (kms_recorder_endpoint_parent_class)->dispose (object);
}
コード例 #11
0
static void
kms_recorder_endpoint_latency_cb (GstPad * pad, KmsMediaType type,
    GstClockTimeDiff t, KmsList * mdata, gpointer user_data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (user_data);
  KmsListIter iter;
  gpointer key, value;
  gchar *name;

  name = gst_element_get_name (self);

  kms_list_iter_init (&iter, mdata);
  while (kms_list_iter_next (&iter, &key, &value)) {
    gchar *id = (gchar *) key;
    StreamE2EAvgStat *stat;

    if (!g_str_has_prefix (id, name)) {
      /* This element did not add this mark to the metada */
      continue;
    }

    stat = (StreamE2EAvgStat *) value;
    stat->avg = KMS_STATS_CALCULATE_LATENCY_AVG (t, stat->avg);
  }
}
コード例 #12
0
static GstCaps *
kms_recorder_endpoint_allowed_caps (KmsElement * kmselement,
    KmsElementPadType type)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (kmselement);
  GstPad *target_pad;
  GstCaps *caps;

  switch (type) {
    case KMS_ELEMENT_PAD_TYPE_VIDEO:
      target_pad = self->priv->video_target;
      break;
    case KMS_ELEMENT_PAD_TYPE_AUDIO:
      target_pad = self->priv->audio_target;
      break;
    default:
      return NULL;
  }

  if (target_pad == NULL) {
    return NULL;
  }

  caps = gst_pad_get_allowed_caps (target_pad);

  return caps;
}
コード例 #13
0
static GstBusSyncReply
bus_sync_signal_handler (GstBus * bus, GstMessage * msg, gpointer data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (data);

  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
    ErrorData *data;

    GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (self),
        GST_DEBUG_GRAPH_SHOW_ALL, GST_ELEMENT_NAME (self));
    kms_base_media_muxer_dot_file (self->priv->mux);

    GST_ERROR_OBJECT (self, "Message %" GST_PTR_FORMAT, msg);

    data = create_error_data (self, msg);

    GST_ERROR_OBJECT (self, "Error: %" GST_PTR_FORMAT, msg);

    gst_task_pool_push (self->priv->pool, kms_recorder_endpoint_post_error,
        data, NULL);
  } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
    gst_task_pool_push (self->priv->pool, kms_recorder_endpoint_on_eos_message,
        self, NULL);
  }
  return GST_BUS_PASS;
}
コード例 #14
0
static void
kms_recorder_endpoint_dispose (GObject * object)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  GST_DEBUG_OBJECT (self, "dispose");

  g_clear_object (&self->priv->loop);

  if (self->priv->mux != NULL) {
    if (kms_muxing_pipeline_get_state (self->priv->mux) != GST_STATE_NULL) {
      GST_ELEMENT_WARNING (self, RESOURCE, BUSY,
          ("Recorder may have buffers to save"),
          ("Disposing recorder when it isn't stopped."));
    }
    kms_muxing_pipeline_set_state (self->priv->mux, GST_STATE_NULL);
    g_clear_object (&self->priv->mux);
  }

  g_mutex_clear (&self->priv->base_time_lock);

  /* clean up as possible.  may be called multiple times */

  G_OBJECT_CLASS (kms_recorder_endpoint_parent_class)->dispose (object);
}
コード例 #15
0
static GstStructure *
kms_recorder_endpoint_stats (KmsElement * obj, gchar * selector)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);
  GstStructure *stats, *e_stats, *l_stats;

  /* chain up */
  stats =
      KMS_ELEMENT_CLASS (kms_recorder_endpoint_parent_class)->stats (obj,
      selector);

  if (!self->priv->stats.enabled) {
    return stats;
  }

  e_stats = kms_stats_get_element_stats (stats);

  if (e_stats == NULL) {
    return stats;
  }

  l_stats = kms_element_get_e2e_latency_stats (self, selector);

  /* Add end to end latency */
  gst_structure_set (e_stats, "e2e-latencies", GST_TYPE_STRUCTURE, l_stats,
      NULL);
  gst_structure_free (l_stats);

  GST_DEBUG_OBJECT (self, "Stats: %" GST_PTR_FORMAT, stats);

  return stats;
}
コード例 #16
0
static void
kms_recorder_endpoint_stopped (KmsUriEndpoint * obj)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);

  kms_recorder_endpoint_change_state (self);

  if (kms_base_media_muxer_get_state (self->priv->mux) >= GST_STATE_PAUSED) {
    kms_recorder_endpoint_send_eos_to_appsrcs (self);
    self->priv->stopping = TRUE;
  }

  kms_recorder_endpoint_remove_pads (self);

  // Reset base time data
  BASE_TIME_LOCK (self);

  g_object_set_data_full (G_OBJECT (self), BASE_TIME_DATA, NULL, NULL);

  self->priv->paused_time = G_GUINT64_CONSTANT (0);
  self->priv->paused_start = GST_CLOCK_TIME_NONE;

  BASE_TIME_UNLOCK (self);

  if (kms_base_media_muxer_get_state (self->priv->mux) < GST_STATE_PAUSED &&
      !self->priv->stopping) {
    kms_base_media_muxer_set_state (self->priv->mux, GST_STATE_NULL);
    kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP);
  }
}
コード例 #17
0
static void
kms_recorder_endpoint_get_property (GObject * object, guint property_id,
    GValue * value, GParamSpec * pspec)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));
  switch (property_id) {
    case PROP_DVR:
      g_value_set_boolean (value, self->priv->use_dvr);
      break;
    case PROP_PROFILE:{
      KmsRecordingProfile profile;

      g_object_get (G_OBJECT (self->priv->controller), "profile", &profile,
          NULL);
      g_value_set_enum (value, profile);
      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));
}
コード例 #18
0
static void
kms_recorder_endpoint_video_valve_added (KmsElement * self, GstElement * valve)
{
  KmsRecorderEndpoint *recorder = KMS_RECORDER_ENDPOINT (self);

  // TODO: This caps should be set using the profile data
  kms_recorder_endpoint_valve_added (recorder, valve, VIDEO_APPSINK,
      VIDEO_APPSRC, "video_%u");
}
コード例 #19
0
static gboolean
kms_recorder_endpoint_query_accept_caps (KmsElement * element, GstPad * pad,
    GstQuery * query)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (element);
  GstCaps *caps, *accept;
  GstElement *appsrc;
  gboolean ret = TRUE;

  switch (kms_element_get_pad_type (element, pad)) {
    case KMS_ELEMENT_PAD_TYPE_VIDEO:
      g_object_get (self->priv->mux, KMS_MUXING_PIPELINE_VIDEO_APPSRC,
          &appsrc, NULL);
      caps = kms_recorder_endpoint_get_caps_from_profile (self,
          KMS_ELEMENT_PAD_TYPE_VIDEO);
      break;
    case KMS_ELEMENT_PAD_TYPE_AUDIO:
      g_object_get (self->priv->mux, KMS_MUXING_PIPELINE_AUDIO_APPSRC,
          &appsrc, NULL);
      caps = kms_recorder_endpoint_get_caps_from_profile (self,
          KMS_ELEMENT_PAD_TYPE_AUDIO);
      break;
    default:
      GST_ERROR_OBJECT (pad, "unknown pad");
      return FALSE;
  }

  if (caps == NULL) {
    GST_ERROR_OBJECT (self, "Can not accept caps without profile");
    gst_query_set_accept_caps_result (query, FALSE);
    g_object_unref (appsrc);
    return TRUE;
  }

  gst_query_parse_accept_caps (query, &accept);

  ret = gst_caps_can_intersect (accept, caps);

  if (ret) {
    GstPad *srcpad;

    srcpad = gst_element_get_static_pad (appsrc, "src");
    ret = gst_pad_peer_query_accept_caps (srcpad, accept);
    gst_object_unref (srcpad);
  } else {
    GST_ERROR_OBJECT (self, "Incompatbile caps %" GST_PTR_FORMAT, caps);
  }

  gst_caps_unref (caps);
  g_object_unref (appsrc);

  gst_query_set_accept_caps_result (query, ret);

  return TRUE;
}
コード例 #20
0
static void
kms_recorder_endpoint_finalize (GObject * object)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  GST_DEBUG_OBJECT (self, "finalize");

  kms_recorder_endpoint_release_pending_requests (self);

  G_OBJECT_CLASS (kms_recorder_endpoint_parent_class)->finalize (object);
}
コード例 #21
0
static void
kms_recorder_endpoint_set_property (GObject * object, guint property_id,
    const GValue * value, GParamSpec * pspec)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));
  switch (property_id) {
    case PROP_DVR:
      self->priv->use_dvr = g_value_get_boolean (value);
      break;
    case PROP_PROFILE:{
      if (self->priv->profile == KMS_RECORDING_PROFILE_NONE) {
        self->priv->profile = g_value_get_enum (value);

        if (self->priv->profile != KMS_RECORDING_PROFILE_NONE) {
          GstElement *sink;
          GstBus *bus;

          sink = kms_recorder_endpoint_create_sink (self);
          self->priv->mux =
              kms_muxing_pipeline_new (KMS_MUXING_PIPELINE_PROFILE,
              self->priv->profile, KMS_MUXING_PIPELINE_SINK, sink, NULL);
          g_object_unref (sink);

          bus = kms_muxing_pipeline_get_bus (self->priv->mux);
          gst_bus_set_sync_handler (bus, bus_sync_signal_handler, self, NULL);
          g_object_unref (bus);

          if (kms_recording_profile_supports_type (self->priv->profile,
                  KMS_ELEMENT_PAD_TYPE_AUDIO)) {
            kms_recorder_endpoint_add_appsink (self,
                KMS_ELEMENT_PAD_TYPE_AUDIO);
          }

          if (kms_recording_profile_supports_type (self->priv->profile,
                  KMS_ELEMENT_PAD_TYPE_VIDEO)) {
            kms_recorder_endpoint_add_appsink (self,
                KMS_ELEMENT_PAD_TYPE_VIDEO);
          }
        }
      } else {
        GST_ERROR_OBJECT (self, "Profile can only be configured once");
      }

      break;
    }
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
  }
  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));
}
コード例 #22
0
static gboolean
kms_recorder_endpoint_post_error (gpointer data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (data);

  gchar *message = (gchar *) g_object_steal_data (G_OBJECT (self), "message");

  GST_ELEMENT_ERROR (self, STREAM, FAILED, ("%s", message), (NULL));
  g_free (message);

  return G_SOURCE_REMOVE;
}
コード例 #23
0
static GstBusSyncReply
bus_sync_signal_handler (GstBus * bus, GstMessage * msg, gpointer data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (data);

  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
    ErrorData *data;

    GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (self),
        GST_DEBUG_GRAPH_SHOW_ALL, GST_ELEMENT_NAME (self));
    kms_base_media_muxer_dot_file (self->priv->mux);

    GST_ERROR_OBJECT (self, "Message %" GST_PTR_FORMAT, msg);

    data = create_error_data (self, msg);

    GST_ERROR_OBJECT (self, "Error: %" GST_PTR_FORMAT, msg);

    gst_task_pool_push (self->priv->pool, kms_recorder_endpoint_post_error,
        data, NULL);
  } else if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) {
    gst_task_pool_push (self->priv->pool, kms_recorder_endpoint_on_eos_message,
        self, NULL);
  } else if ((GST_MESSAGE_TYPE (msg) == GST_MESSAGE_STATE_CHANGED)
      && (GST_OBJECT_CAST (KMS_BASE_MEDIA_MUXER_GET_PIPELINE (self->
                  priv->mux)) == GST_MESSAGE_SRC (msg))) {
    GstState new_state, pending;

    gst_message_parse_state_changed (msg, NULL, &new_state, &pending);

    if (pending == GST_STATE_VOID_PENDING || (pending == GST_STATE_NULL
            && new_state == GST_STATE_READY)) {
      GST_DEBUG_OBJECT (self, "Pipeline changed state to %d", new_state);

      switch (new_state) {
        case GST_STATE_PLAYING:
          kms_recorder_endpoint_state_changed (self,
              KMS_URI_ENDPOINT_STATE_START);
          break;
        case GST_STATE_READY:
          kms_recorder_endpoint_state_changed (self,
              KMS_URI_ENDPOINT_STATE_STOP);
          break;
        default:
          GST_DEBUG_OBJECT (self, "Not raising event");
          break;
      }
    }
  }
  return GST_BUS_PASS;
}
コード例 #24
0
static GstPadProbeReturn
stop_notification_cb (GstPad * srcpad, GstPadProbeInfo * info,
    gpointer user_data)
{
  KmsRecorderEndpoint *recorder = KMS_RECORDER_ENDPOINT (user_data);

  if (GST_EVENT_TYPE (GST_PAD_PROBE_INFO_DATA (info)) != GST_EVENT_EOS)
    return GST_PAD_PROBE_OK;

  kms_loop_idle_add_full (recorder->priv->loop, G_PRIORITY_HIGH_IDLE,
      set_to_null_state_on_EOS, g_object_ref (recorder), g_object_unref);

  return GST_PAD_PROBE_OK;
}
コード例 #25
0
static void
kms_recorder_endpoint_collect_media_stats (KmsElement * obj, gboolean enable)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);

  KMS_ELEMENT_LOCK (self);

  self->priv->stats.enabled = enable;
  kms_recorder_endpoint_update_media_stats (self);

  KMS_ELEMENT_UNLOCK (self);

  KMS_ELEMENT_CLASS
      (kms_recorder_endpoint_parent_class)->collect_media_stats (obj, enable);
}
コード例 #26
0
static gboolean
set_to_null_state_on_EOS (gpointer data)
{
  KmsRecorderEndpoint *recorder = KMS_RECORDER_ENDPOINT (data);

  GST_DEBUG ("Received EOS in pipeline, setting NULL state");

  KMS_ELEMENT_LOCK (KMS_ELEMENT (recorder));

  kms_muxing_pipeline_set_state (recorder->priv->mux, GST_STATE_NULL);

  kms_recorder_endpoint_state_changed (recorder, KMS_URI_ENDPOINT_STATE_STOP);

  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (recorder));

  return G_SOURCE_REMOVE;
}
コード例 #27
0
static gboolean
kms_recorder_endpoint_release_requested_sink_pad (KmsElement * obj,
    GstPad * pad)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);
  gchar *padname = NULL;
  KmsSinkPadData *data;
  gboolean ret = FALSE;

  KMS_ELEMENT_LOCK (KMS_ELEMENT (self));

  ret = self->priv->profile == KMS_RECORDING_PROFILE_KSR;

  if (!ret) {
    goto end;
  }

  padname = gst_pad_get_name (pad);
  data = g_hash_table_lookup (self->priv->sink_pad_data, padname);

  if (data == NULL) {
    GST_ERROR_OBJECT (self, "Can not release requested pad %s", padname);
    goto end;
  }

  if (!data->requested) {
    GST_ERROR_OBJECT (self, "Can not release not requested pad %"
        GST_PTR_FORMAT, pad);
    goto end;
  }

  kms_element_remove_sink_by_type_full (KMS_ELEMENT (self), data->type,
      data->description);
  g_hash_table_remove (self->priv->sink_pad_data, padname);

end:
  KMS_ELEMENT_UNLOCK (KMS_ELEMENT (self));

  g_free (padname);

  return ret;
}
コード例 #28
0
static GstBusSyncReply
bus_sync_signal_handler (GstBus * bus, GstMessage * msg, gpointer data)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (data);

  if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) {
    GError *err = NULL;

    gst_message_parse_error (msg, &err, NULL);
    GST_ERROR_OBJECT (self, "Message %" GST_PTR_FORMAT, msg);
    g_object_set_data_full (G_OBJECT (self), "message",
        g_strdup (err->message), (GDestroyNotify) g_free);

    kms_loop_idle_add_full (self->priv->loop, G_PRIORITY_HIGH_IDLE,
        kms_recorder_endpoint_post_error, g_object_ref (self), g_object_unref);

    g_error_free (err);
  }
  return GST_BUS_PASS;
}
コード例 #29
0
static void
kms_recorder_endpoint_finalize (GObject * object)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (object);

  GST_DEBUG_OBJECT (self, "releasing resources...");

  kms_recorder_endpoint_release_pending_requests (self);
  g_slist_free_full (self->priv->sink_probes,
      (GDestroyNotify) kms_stats_probe_destroy);
  g_hash_table_unref (self->priv->srcs);

  g_hash_table_unref (self->priv->sink_pad_data);
  g_slist_free_full (self->priv->pending_pads, g_free);
  g_hash_table_unref (self->priv->stats.avg_e2e);

  GST_DEBUG_OBJECT (self, "finalized");

  G_OBJECT_CLASS (kms_recorder_endpoint_parent_class)->finalize (object);
}
コード例 #30
0
static void
kms_recorder_endpoint_stopped (KmsUriEndpoint * obj)
{
  KmsRecorderEndpoint *self = KMS_RECORDER_ENDPOINT (obj);
  GstElement *audio_src, *video_src;

  kms_recorder_endpoint_change_state (self);

  /* Close valves */
  kms_recorder_endpoint_close_valves (self);

  // Reset base time data
  audio_src =
      gst_bin_get_by_name (GST_BIN (self->priv->pipeline), AUDIO_APPSRC);
  video_src =
      gst_bin_get_by_name (GST_BIN (self->priv->pipeline), VIDEO_APPSRC);

  KMS_ELEMENT_LOCK (self);

  if (audio_src != NULL) {
    g_object_set_data_full (G_OBJECT (audio_src), BASE_TIME_DATA, NULL, NULL);
    g_object_unref (audio_src);
  }

  if (video_src != NULL) {
    g_object_set_data_full (G_OBJECT (video_src), BASE_TIME_DATA, NULL, NULL);
    g_object_unref (video_src);
  }

  self->priv->paused_time = G_GUINT64_CONSTANT (0);
  self->priv->paused_start = GST_CLOCK_TIME_NONE;

  KMS_ELEMENT_UNLOCK (self);

  if (GST_STATE (self->priv->pipeline) >= GST_STATE_PAUSED) {
    kms_recorder_endpoint_send_eos_to_appsrcs (self);
  } else {
    gst_element_set_state (self->priv->pipeline, GST_STATE_NULL);
    kms_recorder_endpoint_state_changed (self, KMS_URI_ENDPOINT_STATE_STOP);
  }
}