Пример #1
0
static void
remb_event_manager_update_min (RembEventManager * manager, guint bitrate,
    guint ssrc)
{
  RembHashValue *last_value, *value;

  g_mutex_lock (&manager->mutex);
  last_value = g_hash_table_lookup (manager->remb_hash,
      GUINT_TO_POINTER (ssrc));

  if (last_value != NULL && bitrate == last_value->bitrate) {
    last_value->ts = kms_utils_get_time_nsecs ();
    goto end;
  }

  value = remb_hash_value_create (bitrate);
  g_hash_table_insert (manager->remb_hash, GUINT_TO_POINTER (ssrc), value);

  if (bitrate > manager->remb_min) {
    remb_event_manager_calc_min (manager);
  } else {
    remb_event_manager_set_min (manager, bitrate);
  }

end:

  GST_TRACE_OBJECT (manager->pad, "remb_min: %" G_GUINT32_FORMAT,
      manager->remb_min);

  g_mutex_unlock (&manager->mutex);
}
Пример #2
0
static void
remb_event_manager_calc_min (RembEventManager * manager)
{
  guint remb_min = 0;
  GstClockTime time = kms_utils_get_time_nsecs ();
  GstClockTime oldest_time = GST_CLOCK_TIME_NONE;
  GHashTableIter iter;
  gpointer key, v;

  g_hash_table_iter_init (&iter, manager->remb_hash);
  while (g_hash_table_iter_next (&iter, &key, &v)) {
    guint br = ((RembHashValue *) v)->bitrate;
    GstClockTime ts = ((RembHashValue *) v)->ts;

    if (time - ts > REMB_HASH_CLEAR_INTERVAL) {
      GST_TRACE ("Remove entry %" G_GUINT32_FORMAT, GPOINTER_TO_UINT (key));
      g_hash_table_iter_remove (&iter);
      continue;
    }

    if (remb_min == 0) {
      remb_min = br;
    } else {
      remb_min = MIN (remb_min, br);
    }

    oldest_time = MIN (oldest_time, ts);
  }

  manager->oldest_remb_value = oldest_time;
  remb_event_manager_set_min (manager, remb_min);
}
Пример #3
0
static void
buffer_latency_probe_cb (GstBuffer * buffer, ProbeData * pdata)
{
  BufferLatencyValues *blv = (BufferLatencyValues *) pdata->invoke_data;
  GstClockTime time;

  time = kms_utils_get_time_nsecs ();

  kms_buffer_add_buffer_latency_meta (buffer, time, blv->valid, blv->type);
}
Пример #4
0
static RembHashValue *
remb_hash_value_create (guint bitrate)
{
  RembHashValue *value = g_slice_new0 (RembHashValue);

  value->bitrate = bitrate;
  value->ts = kms_utils_get_time_nsecs ();

  return value;
}
Пример #5
0
static void
remb_event_manager_update_min (RembEventManager * manager, guint bitrate,
    guint ssrc)
{
  RembHashValue *last_value;
  GstClockTime time = kms_utils_get_time_nsecs ();
  gboolean new_br = TRUE;

  g_mutex_lock (&manager->mutex);
  last_value = g_hash_table_lookup (manager->remb_hash,
      GUINT_TO_POINTER (ssrc));

  if (last_value != NULL) {
    new_br = bitrate != last_value->bitrate;
    last_value->bitrate = bitrate;
    last_value->ts = kms_utils_get_time_nsecs ();
  } else {
    RembHashValue *value;

    value = remb_hash_value_create (bitrate);
    g_hash_table_insert (manager->remb_hash, GUINT_TO_POINTER (ssrc), value);
  }

  if (bitrate < manager->remb_min) {
    remb_event_manager_set_min (manager, bitrate);
  } else {
    gboolean calc_min;

    calc_min = new_br && (bitrate > manager->remb_min);
    calc_min = calc_min
        || (time - manager->oldest_remb_time > manager->clear_interval);
    if (calc_min) {
      remb_event_manager_calc_min (manager, bitrate);
    }
  }

  GST_TRACE_OBJECT (manager->pad, "remb_min: %" G_GUINT32_FORMAT,
      manager->remb_min);

  g_mutex_unlock (&manager->mutex);
}
Пример #6
0
RembEventManager *
kms_utils_remb_event_manager_create (GstPad * pad)
{
  RembEventManager *manager = g_slice_new0 (RembEventManager);

  g_mutex_init (&manager->mutex);
  manager->remb_hash =
      g_hash_table_new_full (NULL, NULL, NULL, remb_hash_value_destroy);
  manager->pad = g_object_ref (pad);
  manager->probe_id = gst_pad_add_probe (pad, GST_PAD_PROBE_TYPE_EVENT_UPSTREAM,
      remb_probe, manager, NULL);
  manager->oldest_remb_value = kms_utils_get_time_nsecs ();

  return manager;
}
Пример #7
0
guint
kms_utils_remb_event_manager_get_min (RembEventManager * manager)
{
  GstClockTime time = kms_utils_get_time_nsecs ();
  guint ret;

  g_mutex_lock (&manager->mutex);
  if (time - manager->oldest_remb_value > REMB_HASH_CLEAR_INTERVAL) {
    remb_event_manager_calc_min (manager);
  }

  ret = manager->remb_min;
  g_mutex_unlock (&manager->mutex);

  return ret;
}
Пример #8
0
guint
kms_utils_remb_event_manager_get_min (RembEventManager * manager)
{
  GstClockTime time = kms_utils_get_time_nsecs ();
  guint ret;

  g_mutex_lock (&manager->mutex);
  if (time - manager->oldest_remb_time > manager->clear_interval) {
    remb_event_manager_calc_min (manager, 0);
  }

  ret = manager->remb_min;
  g_mutex_unlock (&manager->mutex);

  return ret;
}
Пример #9
0
static gboolean
buffer_for_each_meta_cb (GstBuffer * buffer, GstMeta ** meta, ProbeData * pdata)
{
  BufferLatencyCallback func = (BufferLatencyCallback) pdata->cb;
  GstPad *pad = GST_PAD (pdata->invoke_data);
  KmsBufferLatencyMeta *blmeta;
  GstClockTimeDiff diff;
  GstClockTime now;

  if ((*meta)->info->api != KMS_BUFFER_LATENCY_META_API_TYPE) {
    /* continue iterating */
    return TRUE;
  }

  blmeta = (KmsBufferLatencyMeta *) * meta;

  if (!blmeta->valid) {
    /* Ignore this meta */
    return TRUE;
  }

  if (func == NULL) {
    return TRUE;
  }

  now = kms_utils_get_time_nsecs ();
  diff = GST_CLOCK_DIFF (blmeta->ts, now);

  if (pdata->locked) {
    KMS_BUFFER_LATENCY_DATA_LOCK (blmeta);
  }

  func (pad, blmeta->type, diff, blmeta->data, pdata->user_data);

  if (pdata->locked) {
    KMS_BUFFER_LATENCY_DATA_UNLOCK (blmeta);
  }

  return TRUE;
}
Пример #10
0
static gboolean
get_video_recv_info (KmsRembLocal * rl,
    guint64 * bitrate, guint * fraction_lost, guint64 * packets_rcv_interval)
{
  GValueArray *arr = NULL;
  GValue *val;
  guint i;
  gboolean ret = FALSE;

  if (!KMS_REMB_BASE (rl)->rtpsess) {
    GST_WARNING ("Session object does not exist");
    return ret;
  }

  g_object_get (KMS_REMB_BASE (rl)->rtpsess, "sources", &arr, NULL);

  if (arr == NULL) {
    GST_WARNING ("Sources array not found");
    return ret;
  }

  for (i = 0; i < arr->n_values; i++) {
    GObject *source;
    guint ssrc;
    GstStructure *s;

    val = g_value_array_get_nth (arr, i);
    source = g_value_get_object (val);
    g_object_get (source, "ssrc", &ssrc, "stats", &s, NULL);

    GST_TRACE_OBJECT (source, "source ssrc: %u", ssrc);
    GST_TRACE_OBJECT (KMS_REMB_BASE (rl)->rtpsess, "stats: %" GST_PTR_FORMAT,
        s);

    if (ssrc == rl->remote_ssrc) {
      GstClockTime current_time;
      guint64 octets_received, packets_received;

      if (!gst_structure_get_uint64 (s, "bitrate", bitrate)) {
        break;
      }
      if (!gst_structure_get_uint64 (s, "octets-received", &octets_received)) {
        break;
      }
      if (!gst_structure_get_uint (s, "sent-rb-fractionlost", fraction_lost)) {
        break;
      }
      if (!gst_structure_get_uint64 (s, "packets-received", &packets_received)) {
        break;
      }

      current_time = kms_utils_get_time_nsecs ();

      if (rl->last_time != 0) {
        GstClockTime elapsed = current_time - rl->last_time;
        guint64 bytes_handled = octets_received - rl->last_octets_received;

        *bitrate =
            gst_util_uint64_scale (bytes_handled, 8 * GST_SECOND, elapsed);
        GST_TRACE_OBJECT (KMS_REMB_BASE (rl)->rtpsess,
            "Elapsed %" G_GUINT64_FORMAT " bytes %" G_GUINT64_FORMAT ", rate %"
            G_GUINT64_FORMAT, elapsed, bytes_handled, *bitrate);
      }

      rl->last_time = current_time;
      rl->last_octets_received = octets_received;

      *packets_rcv_interval = packets_received - rl->last_packets_received;
      rl->last_packets_received = packets_received;

      ret = TRUE;
    }

    gst_structure_free (s);

    if (ret) {
      break;
    }
  }

  g_value_array_free (arr);

  return ret;
}