[FFmpeg-cvslog] random_seed: Rewrite the generic clock() based seed code

Michael Niedermayer git at videolan.org
Mon Jan 6 22:23:58 CET 2014


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Mon Jun 11 11:47:59 2012 +0200| [01d245ef4392152dbdc78a6ba4dfa0a6e8b08e6f] | committer: Martin Storsjö

random_seed: Rewrite the generic clock() based seed code

The new code is faster and reuses the previous state in case of
multiple calls.

The previous code could easily end up in near-infinite loops,
if the difference between two clock() calls never was larger than
1.

This makes fate-parseutils finish in finite time when run in wine,
if CryptGenRandom isn't available (which e.g. isn't available if
targeting Windows RT/metro).

Patch originally by Michael Niedermayer but with some modifications
by Martin Storsjö.

Signed-off-by: Martin Storsjö <martin at martin.st>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=01d245ef4392152dbdc78a6ba4dfa0a6e8b08e6f
---

 libavutil/random_seed.c |   51 ++++++++++++++++++++++++++++-------------------
 1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/libavutil/random_seed.c b/libavutil/random_seed.c
index 4680081..26884cb 100644
--- a/libavutil/random_seed.c
+++ b/libavutil/random_seed.c
@@ -31,8 +31,11 @@
 #include <math.h>
 #include <time.h>
 #include "internal.h"
+#include "intreadwrite.h"
+#include "mem.h"
 #include "timer.h"
 #include "random_seed.h"
+#include "sha.h"
 
 static int read_random(uint32_t *dst, const char *file)
 {
@@ -53,34 +56,40 @@ static int read_random(uint32_t *dst, const char *file)
 
 static uint32_t get_generic_seed(void)
 {
+    struct AVSHA *sha = av_sha_alloc();
     clock_t last_t  = 0;
-    int bits        = 0;
-    uint64_t random = 0;
-    unsigned i;
-    float s = 0.000000000001;
+    static uint64_t i = 0;
+    static uint32_t buffer[512] = { 0 };
+    unsigned char digest[20];
+    uint64_t last_i = i;
 
-    for (i = 0; bits < 64; i++) {
+    for (;;) {
         clock_t t = clock();
-        if (last_t && fabs(t - last_t) > s || t == (clock_t) -1) {
-            if (i < 10000 && s < (1 << 24)) {
-                s += s;
-                i = t = 0;
-            } else {
-                random = 2 * random + (i & 1);
-                bits++;
-            }
+
+        if (last_t == t) {
+            buffer[i & 511]++;
+        } else {
+            buffer[++i & 511] += (t - last_t) % 3294638521U;
+            if (last_i && i - last_i > 4 || i - last_i > 64)
+                break;
         }
         last_t = t;
     }
-#ifdef AV_READ_TIME
-    random ^= AV_READ_TIME();
-#else
-    random ^= clock();
-#endif
 
-    random += random >> 32;
-
-    return random;
+    if (!sha) {
+        uint32_t seed = 0;
+        int j;
+        // Unable to allocate an sha context, just xor the buffer together
+        // to create something hopefully unique.
+        for (j = 0; j < 512; j++)
+            seed ^= buffer[j];
+        return seed;
+    }
+    av_sha_init(sha, 160);
+    av_sha_update(sha, (const uint8_t *) buffer, sizeof(buffer));
+    av_sha_final(sha, digest);
+    av_free(sha);
+    return AV_RB32(digest) + AV_RB32(digest + 16);
 }
 
 uint32_t av_get_random_seed(void)



More information about the ffmpeg-cvslog mailing list