mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
221 lines
5.9 KiB
C
221 lines
5.9 KiB
C
|
|
||
|
#ifdef HAVE_CONFIG_H
|
||
|
#include "config.h"
|
||
|
#endif
|
||
|
|
||
|
#ifdef HAVE_GETRUSAGE
|
||
|
#include "gst-cpu-throttling-clock.h"
|
||
|
|
||
|
#include <unistd.h>
|
||
|
#include <sys/resource.h>
|
||
|
|
||
|
#include "gst-cpu-throttling-clock.h"
|
||
|
|
||
|
/**
|
||
|
* SECTION: gst-cpu-throttling-clock
|
||
|
* @title: GstCpuThrottlingClock
|
||
|
* @short_description: TODO
|
||
|
*
|
||
|
* TODO
|
||
|
*/
|
||
|
|
||
|
/* *INDENT-OFF* */
|
||
|
GST_DEBUG_CATEGORY_STATIC (gst_cpu_throttling_clock_debug);
|
||
|
#define GST_CAT_DEFAULT gst_cpu_throttling_clock_debug
|
||
|
|
||
|
struct _GstCpuThrottlingClockPrivate
|
||
|
{
|
||
|
guint wanted_cpu_usage;
|
||
|
|
||
|
GstClock *sclock;
|
||
|
GstClockTime current_wait_time;
|
||
|
GstPoll *timer;
|
||
|
struct rusage last_usage;
|
||
|
|
||
|
GstClockID evaluate_wait_time;
|
||
|
GstClockTime time_between_evals;
|
||
|
};
|
||
|
|
||
|
#define parent_class gst_cpu_throttling_clock_parent_class
|
||
|
G_DEFINE_TYPE_WITH_CODE (GstCpuThrottlingClock, gst_cpu_throttling_clock, GST_TYPE_CLOCK, G_ADD_PRIVATE(GstCpuThrottlingClock))
|
||
|
|
||
|
enum
|
||
|
{
|
||
|
PROP_FIRST,
|
||
|
PROP_CPU_USAGE,
|
||
|
PROP_LAST
|
||
|
};
|
||
|
|
||
|
static GParamSpec *param_specs[PROP_LAST] = { NULL, };
|
||
|
/* *INDENT-ON* */
|
||
|
|
||
|
static void
|
||
|
gst_cpu_throttling_clock_get_property (GObject * object,
|
||
|
guint property_id, GValue * value, GParamSpec * pspec)
|
||
|
{
|
||
|
GstCpuThrottlingClock *self = GST_CPU_THROTTLING_CLOCK (object);
|
||
|
|
||
|
switch (property_id) {
|
||
|
case PROP_CPU_USAGE:
|
||
|
g_value_set_uint (value, self->priv->wanted_cpu_usage);
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_cpu_throttling_clock_set_property (GObject * object,
|
||
|
guint property_id, const GValue * value, GParamSpec * pspec)
|
||
|
{
|
||
|
GstCpuThrottlingClock *self = GST_CPU_THROTTLING_CLOCK (object);
|
||
|
|
||
|
switch (property_id) {
|
||
|
case PROP_CPU_USAGE:
|
||
|
self->priv->wanted_cpu_usage = g_value_get_uint (value);
|
||
|
if (self->priv->wanted_cpu_usage == 0)
|
||
|
self->priv->wanted_cpu_usage = 100;
|
||
|
break;
|
||
|
default:
|
||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static gboolean
|
||
|
gst_transcoder_adjust_wait_time (GstClock * sync_clock, GstClockTime time,
|
||
|
GstClockID id, GstCpuThrottlingClock * self)
|
||
|
{
|
||
|
struct rusage ru;
|
||
|
float delta_usage, usage, coef;
|
||
|
|
||
|
GstCpuThrottlingClockPrivate *priv = self->priv;
|
||
|
|
||
|
getrusage (RUSAGE_SELF, &ru);
|
||
|
delta_usage = GST_TIMEVAL_TO_TIME (ru.ru_utime) -
|
||
|
GST_TIMEVAL_TO_TIME (self->priv->last_usage.ru_utime);
|
||
|
usage =
|
||
|
((float) delta_usage / self->priv->time_between_evals * 100) /
|
||
|
g_get_num_processors ();
|
||
|
|
||
|
self->priv->last_usage = ru;
|
||
|
|
||
|
coef = GST_MSECOND / 10;
|
||
|
if (usage < (gfloat) priv->wanted_cpu_usage) {
|
||
|
coef = -coef;
|
||
|
}
|
||
|
|
||
|
priv->current_wait_time = CLAMP (0,
|
||
|
(GstClockTime) priv->current_wait_time + coef, GST_SECOND);
|
||
|
|
||
|
GST_DEBUG_OBJECT (self,
|
||
|
"Avg is %f (wanted %d) => %" GST_TIME_FORMAT, usage,
|
||
|
self->priv->wanted_cpu_usage, GST_TIME_ARGS (priv->current_wait_time));
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static GstClockReturn
|
||
|
_wait (GstClock * clock, GstClockEntry * entry, GstClockTimeDiff * jitter)
|
||
|
{
|
||
|
GstCpuThrottlingClock *self = GST_CPU_THROTTLING_CLOCK (clock);
|
||
|
|
||
|
if (!self->priv->evaluate_wait_time) {
|
||
|
if (!(self->priv->sclock)) {
|
||
|
GST_ERROR_OBJECT (clock, "Could not find any system clock"
|
||
|
" to start the wait time evaluation task");
|
||
|
} else {
|
||
|
self->priv->evaluate_wait_time =
|
||
|
gst_clock_new_periodic_id (self->priv->sclock,
|
||
|
gst_clock_get_time (self->priv->sclock),
|
||
|
self->priv->time_between_evals);
|
||
|
|
||
|
gst_clock_id_wait_async (self->priv->evaluate_wait_time,
|
||
|
(GstClockCallback) gst_transcoder_adjust_wait_time,
|
||
|
(gpointer) self, NULL);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (G_UNLIKELY (GST_CLOCK_ENTRY_STATUS (entry) == GST_CLOCK_UNSCHEDULED))
|
||
|
return GST_CLOCK_UNSCHEDULED;
|
||
|
|
||
|
if (gst_poll_wait (self->priv->timer, self->priv->current_wait_time)) {
|
||
|
GST_INFO_OBJECT (self, "Something happened on the poll");
|
||
|
}
|
||
|
|
||
|
return GST_CLOCK_ENTRY_STATUS (entry);
|
||
|
}
|
||
|
|
||
|
static GstClockTime
|
||
|
_get_internal_time (GstClock * clock)
|
||
|
{
|
||
|
GstCpuThrottlingClock *self = GST_CPU_THROTTLING_CLOCK (clock);
|
||
|
|
||
|
return gst_clock_get_internal_time (self->priv->sclock);
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_cpu_throttling_clock_dispose (GObject * object)
|
||
|
{
|
||
|
GstCpuThrottlingClock *self = GST_CPU_THROTTLING_CLOCK (object);
|
||
|
|
||
|
if (self->priv->evaluate_wait_time) {
|
||
|
gst_clock_id_unschedule (self->priv->evaluate_wait_time);
|
||
|
gst_clock_id_unref (self->priv->evaluate_wait_time);
|
||
|
self->priv->evaluate_wait_time = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_cpu_throttling_clock_class_init (GstCpuThrottlingClockClass * klass)
|
||
|
{
|
||
|
GObjectClass *oclass = G_OBJECT_CLASS (klass);
|
||
|
GstClockClass *clock_klass = GST_CLOCK_CLASS (klass);
|
||
|
|
||
|
GST_DEBUG_CATEGORY_INIT (gst_cpu_throttling_clock_debug, "cpuclock", 0,
|
||
|
"UriTranscodebin element");
|
||
|
|
||
|
oclass->get_property = gst_cpu_throttling_clock_get_property;
|
||
|
oclass->set_property = gst_cpu_throttling_clock_set_property;
|
||
|
oclass->dispose = gst_cpu_throttling_clock_dispose;
|
||
|
|
||
|
/**
|
||
|
* GstCpuThrottlingClock:cpu-usage:
|
||
|
*
|
||
|
* Since: UNRELEASED
|
||
|
*/
|
||
|
param_specs[PROP_CPU_USAGE] = g_param_spec_uint ("cpu-usage", "cpu-usage",
|
||
|
"The percentage of CPU to try to use with the processus running the "
|
||
|
"pipeline driven by the clock", 0, 100,
|
||
|
100, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
|
||
|
|
||
|
g_object_class_install_properties (oclass, PROP_LAST, param_specs);
|
||
|
|
||
|
clock_klass->wait = GST_DEBUG_FUNCPTR (_wait);
|
||
|
clock_klass->get_internal_time = _get_internal_time;
|
||
|
}
|
||
|
|
||
|
static void
|
||
|
gst_cpu_throttling_clock_init (GstCpuThrottlingClock * self)
|
||
|
{
|
||
|
self->priv = gst_cpu_throttling_clock_get_instance_private (self);
|
||
|
|
||
|
self->priv->current_wait_time = GST_MSECOND;
|
||
|
self->priv->wanted_cpu_usage = 100;
|
||
|
self->priv->timer = gst_poll_new_timer ();
|
||
|
self->priv->time_between_evals = GST_SECOND / 4;
|
||
|
self->priv->sclock = GST_CLOCK (gst_system_clock_obtain ());
|
||
|
|
||
|
|
||
|
getrusage (RUSAGE_SELF, &self->priv->last_usage);
|
||
|
}
|
||
|
|
||
|
GstCpuThrottlingClock *
|
||
|
gst_cpu_throttling_clock_new (guint cpu_usage)
|
||
|
{
|
||
|
return g_object_new (GST_TYPE_CPU_THROTTLING_CLOCK, "cpu-usage",
|
||
|
cpu_usage, NULL);
|
||
|
}
|
||
|
#endif
|