(SDL2) Why is event timestamp not propagated from OS?


#1

Currently, in SDL2 (2.0.0), the timestamp member of the various SDL_Event data structures is filled in in SDL_PushEvent with a call to SDL_GetTicks. Thus, in most cases, timestamp records when the last time SDL_PumpEvents was called. This is not very useful. Instead, timestamp could record when the event actually occurred by propagating timestamps from the various OS event systems. This OS-timestamp would be much more useful to the application, since it gives the time the event actually occurred rather than the time that the application got around to reading it. Unless the application is very carefully written so that SDL_PumpEvents is called frequently with no long delays, the difference between the GetTicks-timestamp and the OS-timestamp will tend to be large–typically on the order of the frame rate, say 30 milliseconds, which is quite perceptible to the user, especially in a game.

Why is the GetTicks-timestamp used instead of propagating the OS-timestamp? At first glance, it looks like it would be straightforward to propagate the OS-timestamp.


#2

Mostly because we don’t have a frame of reference between the OS timestamps
and SDL’s timestamps. Using the OS timestamps would be useful to know the
time between specific events, but not the time relative to now.

If you have a way to solve this, please let me know!On Tue, Jul 16, 2013 at 8:59 AM, sts1hvnx wrote:

**
Currently, in SDL2 (2.0.0), the timestamp member of the various SDL_Event
data structures is filled in in SDL_PushEvent with a call to SDL_GetTicks.
Thus, in most cases, timestamp records when the last time SDL_PumpEvents
was called. This is not very useful. Instead, timestamp could record when
the event actually occurred by propagating timestamps from the various OS
event systems. This OS-timestamp would be much more useful to the
application, since it gives the time the event actually occurred rather
than the time that the application got around to reading it. Unless the
application is very carefully written so that SDL_PumpEvents is called
frequently with no long delays, the difference between the
GetTicks-timestamp and the OS-timestamp will tend to be large–typically on
the order of the frame rate, say 30 milliseconds, which is quite
perceptible to the user, especially in a game.

Why is the GetTicks-timestamp used instead of propagating the
OS-timestamp? At first glance, it looks like it would be straightforward to
propagate the OS-timestamp.


SDL mailing list
SDL at lists.libsdl.org
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org


#3

Here’s one heuristic that might work. Let t_offset be the difference
between SDL time and OS time. Let t0 be the SDL time from the last time
SDL_PumpEvents was called and let t1 be the SDL time of the current call
to SDL_PumpEvents. We know that all OS events arrived sometime between
t0 and t1. Therefore:

SDL_PumpEvents()
{
t1 = SDL_GetTicks();
while (os_event available) {
event = get_os_event();
t1 = SDL_GetTicks(); // Allow for passage of time within function.
event.sdl_time = event.os_time + t_offset;
if (event.sdl_time < t0) {
error = t0 - event.sdl_time;
event.sdl_time += error;
t_offset += error;
} else if (event.sdl_time > t1) {
error = event.sdl_time - t1;
event.sdl_time -= error;
t_offset -= error;
}
}
t0 = t1;
}

If this works, t_offset should converge on a stable and correct value.On 20.07.2013 07:56, Sam Lantinga wrote:

Mostly because we don’t have a frame of reference between the OS timestamps
and SDL’s timestamps. Using the OS timestamps would be useful to know the
time between specific events, but not the time relative to now.


Rainer Deyke (rainerd at eldwood.com)


#4

Rainer Deyke wrote:

… If this works, t_offset should converge on a stable and correct value.

I like it (though I detect a few minor mistakes in your code, such as putting this in SDL_PumpEvents instead of SDL_PushEvent). I think this would work well.

Some thoughts:

  1. I like having separate os_timestamp and sdl_timestamp. This way, if the application programmer wanted accurate event-event time differences, they could use the os_timestamp, and if they wanted accurate event-GetTicks time differences, they could use the sdl_timestamp. However, including both timestamps in SDL2’s event data structures would require changing their layout. Is this still a possibility at this late date?

  2. The timestamp member of SDL2’s event data structures is currently declared Uint32. I think it should be Int32 instead. The reason for this is that with signed integer arithmetic, it’s easier to handle clock overflow. For example, suppose you had two timestamps, t1 and t2, and you wanted to compare them: “if (t1 < t2)”. If t2 is from after a clock overflow, and t1 is before that clock overflow, then that test gives the wrong result. However, if t1 and t2 are signed integer types, it’s easy to make a correct test: “if (t1 - t2 < 0)”. If t1 and t2 are unsigned integer types, it would be a lot trickier and would involve some casting to signed types; “if ((Int32)t1 - (Int32)t2 < 0)” might work, but I’m not certain it would.

  3. Rainer Deyke’s code snippet does not handle clock overflow correctly. If t0, t1, os_time, and sdl_time were all type Int32, then fixing this would be easy: just replace expressions such as “event.sdl_time < t0” with “event.sdl_time - t0 < 0”.

  4. If you guys are too busy to implement this change to SDL2, I can do it. It should only take me a day or two. However, I can only compile and test on Linux (and maybe Win32 if I can figure out how to cross-compile), so my implementation for other platforms would probably have some simple errors that someone else would have to find. Let me know if you want me to do it.


#5

OS?
Message-ID: <1374335350.m2f.38154 at forums.libsdl.org>
Content-Type: text/plain; charset=“iso-8859-1”

Rainer Deyke wrote:

… If this works, t_offset should converge on a stable and correct
value.

I like it (though I detect a few minor mistakes in your code, such as
putting this in SDL_PumpEvents instead of SDL_PushEvent). I think this
would work well.

Some thoughts:

  1. I like having separate os_timestamp and sdl_timestamp. This way, if the
    application programmer wanted accurate event-event time differences, they
    could use the os_timestamp, and if they wanted accurate event-GetTicks time
    differences, they could use the sdl_timestamp. However, including both
    timestamps in SDL2’s event data structures would require changing their
    layout. Is this still a possibility at this late date?

I think that would depend on whether the SDL_Event copy function winds
up in the linker-stub or the dynamic-library:

  1. If it winds up in the dynamic library then we would need to add
    another set of event functions, so that the ABI didn’t get broken (the
    alternative is that you screw around with the contents of the stack,
    or wherever else you declared the event instance at);
  2. If it winds up in the linker-stub then the program will always be
    using the same copy function because it carries it around with itself,
    thereby causing anything added at the end of the current event
    structure to simply be ignored.

As for adding data members, as long as they go at the end of the
structure there shouldn’t ever be a problem inside of the structure
itself. That having been said, it would be nice to have a structure
member that carries the actual size of the event, so that e.g.
libraries that care about the extra data can know if it’s there or
not. Thus, if another set of event functions have to be added, perhaps
make them use a wrapper structure consisting of a size followed by the
actual SDL_Event instance?> Date: Sat, 20 Jul 2013 08:49:11 -0700

From: “sts1hvnx”
To: sdl at lists.libsdl.org
Subject: Re: [SDL] (SDL2) Why is event timestamp not propagated from


#6

Hello, some thread necromancy here. Has there been any progress on this front? It’s actually something that we’re very interested in for our application (a brain science experiment concerned with as-accurate-as-possible timestamps of keypresses.)

I agree that using a synchronization algorithm would work. A potentially even easier solution would be during initialization of the system. Just perform one call to whatever clock is timestamping the OS event timestamp. For example, in OSX the system uptime clock ( [[NSProcessInfo processInfo] systemUptime] ). Now you know the relationship between the two clocks and can simply perform subtraction to convert between them, right? This would only fail if the call to the operating system was somehow unreliable or separated in time from the corresponding call to SDL’s high precision clock.


#7

Ping me about this in a bit and I’ll take another look at it. I can’t promise anything, but it sounds like something worth exploring further.


#8

Thanks very much for your response, icculus. I’ll definitely ping you with what I know after the weekend, and I’ll make another post here in case anybody else stumbles upon this or is interested.


#9

Quick update: I’m implementing this in a different environment (Unity3D) and I’m not sure if my implementation is working quite right yet. Once I have something I’m confident about I’ll post here.