implement frame rate limiter
Stefan Schuermans

Stefan Schuermans commited on 2014-01-03 00:52:55
Showing 23 changed files, with 667 additions and 10 deletions.

... ...
@@ -106,6 +106,7 @@
106 106
         <li><a href="player.html">Player</a></li>
107 107
         <li><a href="printer.html">Printer</a></li>
108 108
         <li><a href="priority.html">Priority</a></li>
109
+        <li><a href="ratelimiter.html">Rate Limiter</a></li>
109 110
         <li><a href="resizer.html">Resizer</a></li>
110 111
         <li><a href="scaler.html">Scaler</a></li>
111 112
         <li><a href="udp4phone.html">UDP4 Phone Connector</a></li>
... ...
@@ -0,0 +1,47 @@
1
+<html>
2
+  <head>
3
+    <title>Blinker - Rate Limiter</title>
4
+  </head>
5
+  <body>
6
+    <h1>Blinker - Rate Limiter</h1>
7
+    <p>
8
+      The frame rate limiter module reduces the frame rate of a stream by
9
+      delaying frames and/or dropping frames.
10
+      It receives a single input stream and passes it on with a possibly
11
+      reduced frame rate.
12
+      <br>
13
+      If a frame (frame B) occurs to fast after the previous one (frame A),
14
+      it is delayed so that the maximum frame rate is not violated. If another
15
+      frame (frame C) occurs before frame B is forwarded, frame B is dropped
16
+      and frame C will be forwarded with some delay (if no newer frame (frame D)
17
+      is received before frame C is forwarded).
18
+    </p>
19
+    <h2>Configuration</h2>
20
+    <p>
21
+      The configuration of the frame rate limiter module with name
22
+      <code>NAME</code> is located in the <code>ratelimiters/NAME</code>
23
+      subdirectory.
24
+    </p>
25
+    <h3>Input Stream</h3>
26
+    <p>
27
+      The file <code>instream</code> contains the name of the stream to
28
+      receive.
29
+      The frames received from this stream are passed to the output stream
30
+      if the delay in between is high enough so the maximum frame rate is
31
+      not violated.
32
+    </p>
33
+    <h3>Maximum Frame Rate</h3>
34
+    <p>
35
+      The file <code>maxrate</code> specifies the maximum allowed frame rate
36
+      format of the output stream in frames per second.
37
+      The file must contain a single floating point value, e.g.
38
+      <code>2.0</code> for limiting the frame rate to two frames per second.
39
+    </p>
40
+    <h3>Output Stream</h3>
41
+    <p>
42
+      The file <code>outstream</code> contains the name of the stream to
43
+      which to send the frames with reduced frame rate.
44
+    </p>
45
+  </body>
46
+</html>
47
+
... ...
@@ -6,7 +6,7 @@ CPP=g++
6 6
 CONFIG=
7 7
 DEFINE=-DBLINKER_CONFIG="\"$(CONFIG)\""
8 8
 INCLUDE=-Inoarch -Ilinux
9
-CFLAGS=-Wall -Wextra -g2
9
+CFLAGS=-Wall -Wextra -Werror -O2 -g2
10 10
 LDFLAGS=
11 11
 LIBS=-lBlinkenLib
12 12
 
... ...
@@ -4,6 +4,7 @@
4 4
    a blinkenarea.org project */
5 5
 
6 6
 #include <errno.h>
7
+#include <math.h>
7 8
 #include <stdint.h>
8 9
 #include <sys/time.h>
9 10
 #include <time.h>
... ...
@@ -130,6 +131,16 @@ Time Time::operator-(const Time &that) const
130 131
 
131 132
 //@}
132 133
 
134
+/**
135
+ * @brief convert from floating point seconds
136
+ * @param[in] s time in seconds
137
+ */
138
+void Time::fromFloatSec(float s)
139
+{
140
+  m_sec = (int64_t)truncf(s);
141
+  m_ns  = (int64_t)((s - m_sec) * 1.0e9);
142
+}
143
+
133 144
 /**
134 145
  * @brief convert from milliseconds
135 146
  * @param[in] ms milliseconds
... ...
@@ -55,6 +55,12 @@ public:
55 55
   Time operator-(const Time &that) const;
56 56
   //@}
57 57
 
58
+  /**
59
+   * @brief convert from floating point seconds
60
+   * @param[in] s time in seconds
61
+   */
62
+  void fromFloatSec(float s);
63
+
58 64
   /**
59 65
    * @brief convert from milliseconds
60 66
    * @param[in] ms milliseconds
... ...
@@ -85,6 +91,7 @@ protected:
85 91
   void fix();
86 92
 
87 93
 protected:
94
+public:
88 95
   int64_t m_sec; ///< seconds
89 96
   int64_t m_ns;  ///< nanoseconds
90 97
 }; // class Time
... ...
@@ -3,7 +3,6 @@
3 3
    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4 4
    a blinkenarea.org project */
5 5
 
6
-#include <iostream>
7 6
 #include <stdlib.h>
8 7
 #include <string>
9 8
 #include <string.h>
... ...
@@ -0,0 +1,128 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <math.h>
7
+#include <sstream>
8
+#include <string>
9
+
10
+#include "Float.h"
11
+#include "StringParser.h"
12
+
13
+namespace Blinker {
14
+
15
+/// constructor
16
+Float::Float():
17
+  m_float(0.0f)
18
+{
19
+}
20
+
21
+/**
22
+ * @brief parse from string format
23
+ * @param[in] str string format
24
+ * @return if parsing was successful
25
+ */
26
+bool Float::fromStr(const std::string &str)
27
+{
28
+  StringParser parser(str);
29
+  float fl;
30
+
31
+  if (!parser.floatVal(fl) ||
32
+      !parser.isDone())
33
+    return false;
34
+  m_float = fl;
35
+  return true;
36
+}
37
+
38
+/**
39
+ * @brief convert to string format
40
+ * @return string format
41
+ */
42
+std::string Float::toStr() const
43
+{
44
+  std::stringstream strm;
45
+  /* output float manually to get floats with dot as decimal separator for
46
+   * all locales */
47
+  float val = m_float;
48
+  int exp, dot_pos, e_exp, total_digits, e_scale;
49
+  // output sign
50
+  if (val < 0.0f) {
51
+    strm << '-';
52
+    val = -val;
53
+  }
54
+  // get exponent
55
+  exp = floorf(log10f(val)) + 1;
56
+  val *= pow(0.1f, exp);
57
+  // fix val into range (1.0,0.1] in case of numerical instabilities
58
+  if (val >= 1.0f) {
59
+    val *= 0.1f;
60
+    exp++;
61
+  }
62
+  if (val < 0.1f) {
63
+    val *= 10.0f;
64
+    exp--;
65
+  }
66
+  // scientific notation
67
+  if (exp < -3 || exp > 5) {
68
+    dot_pos = 1;
69
+    e_exp = exp - 1;
70
+  }
71
+  // plain notation
72
+  else {
73
+    dot_pos = exp;
74
+    e_exp = 0;
75
+  }
76
+  // digits before dot
77
+  total_digits = 0;
78
+  if (dot_pos > 0) {
79
+    while (dot_pos > 0) {
80
+      val *= 10.0f;
81
+      unsigned int digit = (unsigned int)val;
82
+      val -= digit;
83
+      strm << (char)('0' + digit);
84
+      dot_pos--;
85
+      total_digits++;
86
+    }
87
+  } else {
88
+    strm << '0';
89
+  }
90
+  // decimal dot
91
+  strm << '.';
92
+  // zeros after dot
93
+  while (dot_pos < 0) {
94
+    strm << '0';
95
+    dot_pos++;
96
+  }
97
+  // digits after dot
98
+  while (total_digits < 7) {
99
+    val *= 10.0f;
100
+    unsigned int digit = (unsigned int)val;
101
+    val -= digit;
102
+    strm << (char)('0' + digit);
103
+    total_digits++;
104
+  }
105
+  // exponent
106
+  if (e_exp != 0) {
107
+    strm << 'e';
108
+    // exponent sign
109
+    if (e_exp < 0) {
110
+      strm << '-';
111
+      e_exp = -e_exp;
112
+    }
113
+    // exponent value
114
+    e_scale = 1;
115
+    while (e_scale * 10 <= e_exp)
116
+      e_scale *= 10;
117
+    do {
118
+      unsigned int digit = e_exp / e_scale;
119
+      strm << (char)('0' + digit);
120
+      e_exp -= digit * e_scale;
121
+      e_scale /= 10;
122
+    } while (e_scale > 0);
123
+  }
124
+  return strm.str();
125
+}
126
+
127
+} // namespace Blinker
128
+
... ...
@@ -0,0 +1,41 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef BLINKER_FLOAT_H
7
+#define BLINKER_FLOAT_H
8
+
9
+#include <string>
10
+
11
+namespace Blinker {
12
+
13
+/// a floating point value
14
+class Float
15
+{
16
+public:
17
+  /// constructor
18
+  Float();
19
+
20
+public:
21
+  /**
22
+   * @brief parse from string format
23
+   * @param[in] str string format
24
+   * @return if parsing was successful
25
+   */
26
+  bool fromStr(const std::string &str);
27
+
28
+  /**
29
+   * @brief convert to string format
30
+   * @return string format
31
+   */
32
+  std::string toStr() const;
33
+
34
+public:
35
+  float m_float; ///< floating point value
36
+}; // class Float
37
+
38
+} // namespace Blinker
39
+
40
+#endif // #ifndef BLINKER_FLOAT_H
41
+
... ...
@@ -0,0 +1,20 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef BLINKER_FLOATFILE_H
7
+#define BLINKER_FLOATFILE_H
8
+
9
+#include "SettingFile_impl.h"
10
+#include "Float.h"
11
+
12
+namespace Blinker {
13
+
14
+/// setting file containting floating point value
15
+typedef SettingFile<Float> FloatFile;
16
+
17
+} // namespace Blinker
18
+
19
+#endif // #ifndef BLINKER_FLOATFILE_H
20
+
... ...
@@ -0,0 +1,46 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include "Float.h"
7
+#include "Rate.h"
8
+
9
+#define BLINKER_RATE_MIN (0.001f)
10
+
11
+namespace Blinker {
12
+
13
+/// constructor
14
+Rate::Rate():
15
+  m_rate(1.0f)
16
+{
17
+}
18
+
19
+/**
20
+ * @brief parse from string format
21
+ * @param[in] str string format
22
+ * @return if parsing was successful
23
+ */
24
+bool Rate::fromStr(const std::string &str)
25
+{
26
+  Float fl;
27
+
28
+  if (!fl.fromStr(str) || fl.m_float < BLINKER_RATE_MIN)
29
+    return false;
30
+  m_rate = fl.m_float;
31
+  return true;
32
+}
33
+
34
+/**
35
+ * @brief convert to string format
36
+ * @return string format
37
+ */
38
+std::string Rate::toStr() const
39
+{
40
+  Float fl;
41
+  fl.m_float = m_rate;
42
+  return fl.toStr();
43
+}
44
+
45
+} // namespace Blinker
46
+
... ...
@@ -0,0 +1,41 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef BLINKER_RATE_H
7
+#define BLINKER_RATE_H
8
+
9
+#include <string>
10
+
11
+namespace Blinker {
12
+
13
+/// a frame rate
14
+class Rate
15
+{
16
+public:
17
+  /// constructor
18
+  Rate();
19
+
20
+public:
21
+  /**
22
+   * @brief parse from string format
23
+   * @param[in] str string format
24
+   * @return if parsing was successful
25
+   */
26
+  bool fromStr(const std::string &str);
27
+
28
+  /**
29
+   * @brief convert to string format
30
+   * @return string format
31
+   */
32
+  std::string toStr() const;
33
+
34
+public:
35
+  float m_rate; ///< frame rate in frames per second
36
+}; // class Rate
37
+
38
+} // namespace Blinker
39
+
40
+#endif // #ifndef BLINKER_RATE_H
41
+
... ...
@@ -0,0 +1,20 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef BLINKER_RATEFILE_H
7
+#define BLINKER_RATEFILE_H
8
+
9
+#include "SettingFile_impl.h"
10
+#include "Rate.h"
11
+
12
+namespace Blinker {
13
+
14
+/// setting file containting frame rate
15
+typedef SettingFile<Rate> RateFile;
16
+
17
+} // namespace Blinker
18
+
19
+#endif // #ifndef BLINKER_RATEFILE_H
20
+
... ...
@@ -0,0 +1,132 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#include <stdlib.h>
7
+#include <string>
8
+
9
+#include <BlinkenLib/BlinkenFrame.h>
10
+
11
+#include "Directory.h"
12
+#include "File.h"
13
+#include "InStreamFile.h"
14
+#include "Mgrs.h"
15
+#include "Module.h"
16
+#include "OutStreamFile.h"
17
+#include "RateFile.h"
18
+#include "RateLimiter.h"
19
+#include "StreamRecv.h"
20
+#include "Time.h"
21
+
22
+namespace Blinker {
23
+
24
+/**
25
+ * @brief constructor
26
+ * @param[in] name module name
27
+ * @param[in] mgrs managers
28
+ * @param[in] dirBase base directory
29
+ */
30
+RateLimiter::RateLimiter(const std::string &name, Mgrs &mgrs,
31
+                         const Directory &dirBase):
32
+  Module(name, mgrs, dirBase),
33
+  m_fileInStream(dirBase.getFile("instream"), mgrs.m_streamMgr),
34
+  m_fileMaxRate(dirBase.getFile("maxrate")),
35
+  m_fileOutStream(dirBase.getFile("outstream"), mgrs.m_streamMgr),
36
+  m_last(Time::now() - Time(1))
37
+{
38
+  // set up
39
+  getMaxRate();
40
+  m_fileInStream.setStreamRecv(this);
41
+}
42
+
43
+/// virtual destructor
44
+RateLimiter::~RateLimiter()
45
+{
46
+  // clean up
47
+  m_fileInStream.setStreamRecv(NULL);
48
+}
49
+
50
+/// check for update of configuration
51
+void RateLimiter::updateConfig()
52
+{
53
+  // stream name or format file was modified -> re-get stream or format
54
+  if (m_fileInStream.checkModified())
55
+    m_fileInStream.update();
56
+  if (m_fileMaxRate.checkModified())
57
+    getMaxRate();
58
+  if (m_fileOutStream.checkModified())
59
+    m_fileOutStream.update();
60
+}
61
+
62
+/// callback when requested time reached
63
+void RateLimiter::timeCall()
64
+{
65
+  // try to send current frame to output stream
66
+  sendFrame();
67
+}
68
+
69
+/**
70
+ * @brief set current frame
71
+ * @param[in] stream stream name
72
+ * @param[in] pFrame current frame (NULL for none)
73
+ */
74
+void RateLimiter::setFrame(const std::string &stream, stBlinkenFrame *pFrame)
75
+{
76
+  procFrame(pFrame);
77
+  (void)stream; // unused
78
+}
79
+
80
+/// (re-)get maximum frame rate to limit to
81
+void RateLimiter::getMaxRate()
82
+{
83
+  // read maximum frame rate from file
84
+  m_fileMaxRate.update();
85
+
86
+  // send current frame to output stream
87
+  sendFrame();
88
+}
89
+
90
+/// send current frame to output stream
91
+void RateLimiter::sendFrame()
92
+{
93
+  // get current frame from input stream and process it
94
+  procFrame(m_fileInStream.getCurFrame());
95
+}
96
+
97
+/**
98
+ * @brief process frame
99
+ * @param[in] pFrame frame to process (NULL for none)
100
+ */
101
+void RateLimiter::procFrame(stBlinkenFrame *pFrame)
102
+{
103
+  // get current time
104
+  Time now = Time::now();
105
+
106
+  // get minimum time between two frames
107
+  Time minDelta(1); // default to 1 fps
108
+  if (m_fileMaxRate.m_valid)
109
+    minDelta.fromFloatSec(1.0f / m_fileMaxRate.m_obj.m_rate);
110
+
111
+  // minimum time not yet elapsed
112
+  if (now - m_last < minDelta) {
113
+    // schedule callback when minimum time has elapsed
114
+    m_mgrs.m_callMgr.requestTimeCall(this, m_last + minDelta);
115
+    // do not forward anything now
116
+    return;
117
+  }
118
+
119
+  // no frame or no valid frame rate -> pass "no frame"
120
+  if (!pFrame || !m_fileMaxRate.m_valid) {
121
+    m_last = now; // save time of last forwarded "no frame"
122
+    m_fileOutStream.setFrame(NULL);
123
+    return;
124
+  }
125
+
126
+  // pass frame to output stream
127
+  m_last = now; // save time of last forwarded frame
128
+  m_fileOutStream.setFrame(pFrame);
129
+}
130
+
131
+} // namespace Blinker
132
+
... ...
@@ -0,0 +1,86 @@
1
+/* Blinker
2
+   Copyright 2011-2014 Stefan Schuermans <stefan@blinkenarea.org>
3
+   Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4
+   a blinkenarea.org project */
5
+
6
+#ifndef BLINKER_RATELIMITER_H
7
+#define BLINKER_RATELIMITER_H
8
+
9
+#include <string>
10
+
11
+#include <BlinkenLib/BlinkenFrame.h>
12
+
13
+#include "Directory.h"
14
+#include "File.h"
15
+#include "InStreamFile.h"
16
+#include "Mgrs.h"
17
+#include "Module.h"
18
+#include "OutStreamFile.h"
19
+#include "RateFile.h"
20
+#include "StreamRecv.h"
21
+#include "Time.h"
22
+#include "TimeCallee.h"
23
+
24
+namespace Blinker {
25
+
26
+/// a stream frame rate limiter
27
+class RateLimiter: public Module, public StreamRecv, public TimeCallee
28
+{
29
+public:
30
+  /**
31
+   * @brief constructor
32
+   * @param[in] name module name
33
+   * @param[in] mgrs managers
34
+   * @param[in] dirBase base directory
35
+   */
36
+  RateLimiter(const std::string &name, Mgrs &mgrs, const Directory &dirBase);
37
+
38
+  /// virtual destructor
39
+  virtual ~RateLimiter();
40
+
41
+private:
42
+  /// copy constructor disabled
43
+  RateLimiter(const RateLimiter &that);
44
+
45
+  /// assignment operator disabled
46
+  const RateLimiter & operator=(const RateLimiter &that);
47
+
48
+public:
49
+  /// check for update of configuration
50
+  virtual void updateConfig();
51
+
52
+  /// callback when requested time reached
53
+  virtual void timeCall();
54
+
55
+  /**
56
+   * @brief set current frame
57
+   * @param[in] stream stream name
58
+   * @param[in] pFrame current frame (NULL for none)
59
+   */
60
+  virtual void setFrame(const std::string &stream, stBlinkenFrame *pFrame);
61
+
62
+protected:
63
+  /// (re-)get maximum frame rate to limit to
64
+  void getMaxRate();
65
+
66
+  /// send current frame to output stream
67
+  void sendFrame();
68
+
69
+  /**
70
+   * @brief process frame
71
+   * @param[in] pFrame frame to process (NULL for none)
72
+   */
73
+  void procFrame(stBlinkenFrame *pFrame);
74
+
75
+protected:
76
+  InStreamFile  m_fileInStream;  ///< input stream name file
77
+  RateFile      m_fileMaxRate;   ///< maximum frame rate file
78
+  OutStreamFile m_fileOutStream; ///< output stream name file
79
+
80
+  Time m_last; ///< time at which the last frame was forwarded
81
+}; // class RateLimiter
82
+
83
+} // namespace Blinker
84
+
85
+#endif // #ifndef BLINKER_RATELIMITER_H
86
+
... ...
@@ -3,7 +3,6 @@
3 3
    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4 4
    a blinkenarea.org project */
5 5
 
6
-#include <iostream>
7 6
 #include <stdlib.h>
8 7
 #include <string>
9 8
 
... ...
@@ -125,7 +124,7 @@ void Resizer::procFrame(stBlinkenFrame *pFrame)
125 124
   // resize frame
126 125
   BlinkenFrameResize(pProcFrame, height, width, channels, maxval);
127 126
 
128
-  // pass process frame to output stream
127
+  // pass processed frame to output stream
129 128
   m_fileOutStream.setFrame(pProcFrame);
130 129
 
131 130
   // free cloned frame
... ...
@@ -3,7 +3,6 @@
3 3
    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4 4
    a blinkenarea.org project */
5 5
 
6
-#include <iostream>
7 6
 #include <stdlib.h>
8 7
 #include <string>
9 8
 
... ...
@@ -120,7 +119,7 @@ void Scaler::procFrame(stBlinkenFrame *pFrame)
120 119
   // scale frame
121 120
   BlinkenFrameScale(pProcFrame, height, width);
122 121
 
123
-  // pass process frame to output stream
122
+  // pass processed frame to output stream
124 123
   m_fileOutStream.setFrame(pProcFrame);
125 124
 
126 125
   // free cloned frame
... ...
@@ -3,6 +3,7 @@
3 3
    Copyleft GNU public license - http://www.gnu.org/copyleft/gpl.html
4 4
    a blinkenarea.org project */
5 5
 
6
+#include <math.h>
6 7
 #include <string>
7 8
 
8 9
 #include "StringParser.h"
... ...
@@ -117,7 +118,7 @@ bool StringParser::uintMin(unsigned int min, unsigned int &uint)
117 118
  */
118 119
 bool StringParser::sintNo(int &sint)
119 120
 {
120
-  int sign;
121
+  int sign = 1;
121 122
   unsigned int uint;
122 123
   bool ret;
123 124
   sint = 0;
... ...
@@ -131,9 +132,6 @@ bool StringParser::sintNo(int &sint)
131 132
         sign = -1;
132 133
         ++m_it;
133 134
         break;
134
-      default:
135
-        sign = 1;
136
-        break;
137 135
     }
138 136
   }
139 137
   ret = uintNo(uint);
... ...
@@ -141,6 +139,76 @@ bool StringParser::sintNo(int &sint)
141 139
   return ret;
142 140
 }
143 141
 
142
+/**
143
+ * @brief parse floating point value
144
+ * @param[out] fl floating point value parsed from string
145
+ * @return if parsing was successful
146
+ */
147
+bool StringParser::floatVal(float &fl)
148
+{
149
+  /* parse float manually to accept floats with dot as decimal separator for
150
+   * all locales */
151
+  int sign = 1, exp_sign = 1;
152
+  float val = 0.0f, frac_val = 0.1f, exp_val = 0.0f;
153
+  bool ret = false;
154
+  // sign
155
+  if (m_it != m_str.end()) {
156
+    switch (*m_it) {
157
+      case '+':
158
+        sign = 1.0f;
159
+        ++m_it;
160
+        break;
161
+      case '-':
162
+        sign = -1.0f;
163
+        ++m_it;
164
+        break;
165
+    }
166
+  }
167
+  // digits before decimal pdot
168
+  while (m_it != m_str.end() && *m_it >= '0' && *m_it <= '9') {
169
+    val *= 10.0f;
170
+    val += *m_it - '0';
171
+    ++m_it;
172
+    ret = true;
173
+  }
174
+  // decimal dot
175
+  if (m_it != m_str.end() && *m_it == '.') {
176
+    ++m_it;
177
+    ret = true;
178
+    // digits after decimal dot
179
+    while (m_it != m_str.end() && *m_it >= '0' && *m_it <= '9') {
180
+      val += (*m_it - '0') * frac_val;
181
+      ++m_it;
182
+      frac_val *= 0.1f;
183
+    }
184
+  }
185
+  // exponent
186
+  if (m_it != m_str.end() && (*m_it == 'e' || *m_it == 'E')) {
187
+    ++m_it;
188
+    // exponent sign
189
+    if (m_it != m_str.end()) {
190
+      switch (*m_it) {
191
+        case '+':
192
+          exp_sign = 1.0f;
193
+          ++m_it;
194
+          break;
195
+        case '-':
196
+          exp_sign = -1.0f;
197
+          ++m_it;
198
+          break;
199
+      }
200
+    }
201
+    // exponent digits
202
+    while (m_it != m_str.end() && *m_it >= '0' && *m_it <= '9') {
203
+      exp_val *= 10.0f;
204
+      exp_val += *m_it - '0';
205
+      ++m_it;
206
+    }
207
+  }
208
+  fl = sign * val * pow(10.0, exp_sign * exp_val);
209
+  return ret;
210
+}
211
+
144 212
 /**
145 213
  * @brief parse until a delimiter is found
146 214
  * @param[in] delim set of delimiter characters
... ...
@@ -65,6 +65,13 @@ public:
65 65
    */
66 66
   bool sintNo(int &sint);
67 67
 
68
+  /**
69
+   * @brief parse floating point value
70
+   * @param[out] fl floating point value parsed from string
71
+   * @return if parsing was successful
72
+   */
73
+  bool floatVal(float &fl);
74
+
68 75
   /**
69 76
    * @brief parse until a delimiter is found
70 77
    * @param[in] delim set of delimiter characters
... ...
@@ -19,6 +19,7 @@
19 19
 #include "Player.h"
20 20
 #include "Printer.h"
21 21
 #include "Priority.h"
22
+#include "RateLimiter.h"
22 23
 #include "Resizer.h"
23 24
 #include "Scaler.h"
24 25
 #include "Udp4Phone.h"
... ...
@@ -49,6 +50,7 @@ void run(const std::string &dirConfig)
49 50
   MODULEMGR(Printer,      printers);
50 51
   MODULEMGR(Priority,     priorities);
51 52
   MODULEMGR(Resizer,      resizers);
53
+  MODULEMGR(RateLimiter,  ratelimiters);
52 54
   MODULEMGR(Scaler,       scalers);
53 55
   MODULEMGR(Udp4Phone,    udp4phones);
54 56
   MODULEMGR(Udp4Receiver, udp4receivers);
55 57