API fragmentation?

Hi;

I’m just getting back into developing a Roku channel after a long period of not being involved. From what I can see, there appears to be API fragmentation depending on the Roku player supported (first gen vs 2nd gen). Also, I’ve seen some reports that channels that work on Roku 1 won’t work on a Roku 2. Someone correct me.

Newer firmwares have added new SDK features and functionality and not everything that you can do in 4.8 is possible in 3.1. You should always test any channel you develop on all the different firmwares you intend to deploy it to.

I’m not sure about channels that work on older boxes not working on Roku2. It’s not something I’ve heard of.

As Chris mentioned above, there are some newer API’s and features that are not available on the initial Roku players (Smooth Streaming for example), but we strive to be fully forward compatible.

If you find any issues with apps that work on Roku 1 players that do not work on current models, please let us know and we will investigate.

Cheers,
Jon

There’s not much you can do about the speed variations? - meaning on roku1 roscreen drawing from tmp files is slower, and on roku2 the wait command for message ports has an enforced minimum delay of 10-15ms that roku 1 doesn’t have. It would be great if both roku 1 and roku 2 could run at the same speeds for animation and games.

old thread on the roku 2 and the message port wait delays -
viewtopic.php?f=34&t=46452&hilit=goto

If your game depends on timing, your frame rendering loop should use timers to control the frame rate.

Our simple2d sample application just renders frames as fast as it can and you do see a difference in game timing between the Roku1 and Roku2. You could add a wait() in that loop with a timeout that you calculate to be the next frame rendering time.

Of course, it’s possible that the Roku1 will not be able to support the frame rates that the Roku 2 does but your timers in the render loop should keep the timing of your game the same on both platforms.

–Kevin

“RokuKevin” wrote:
If your game depends on timing, your frame rendering loop should use timers to control the frame rate.

Our simple2d sample application just renders frames as fast as it can and you do see a difference in game timing between the Roku1 and Roku2. You could add a wait() in that loop with a timeout that you calculate to be the next frame rendering time.

Of course, it’s possible that the Roku1 will not be able to support the frame rates that the Roku 2 does but your timers in the render loop should keep the timing of your game the same on both platforms.

–Kevin
Kevin,
Wait() and Sleep() aren’t consistent on the Roku 2 firmware, so they really can’t be used for timing. See this thread for more information on that: viewtopic.php?f=34&t=46452
Hopefully that will be fixed at some point in the near future.

I looked into the wait() inaccuracy on the Roku 2, and unfortunately we have had an open bug on this platform that affects both wait() and sleep(). Enabling the high resolution timer in these methods caused instability in the firmware so it is currently disabled. We’ll have to fix these before using wait() or sleep() becomes a viable option for this use case.

In the meantime, you could use the rotimespan component to get a high resolution timer and check for events in the busy-wait loop with a call to msgport.getmessage() (which does return immediately whether there’s a message or not).

–Kevin

all right. Thanks. With the high resolution timer going like that, screenshots take a lot longer to process, but that’s the price to be paid. :slightly_smiling_face:

Sorry, haven’t been following this as I should have; thanks Chris and others for the replies.

“RokuKevin” wrote:
I looked into the wait() inaccuracy on the Roku 2, and unfortunately we have had an open bug on this platform that affects both wait() and sleep(). Enabling the high resolution timer in these methods caused instability in the firmware so it is currently disabled. We’ll have to fix these before using wait() or sleep() becomes a viable option for this use case.

In the meantime, you could use the rotimespan component to get a high resolution timer and check for events in the busy-wait loop with a call to msgport.getmessage() (which does return immediately whether there’s a message or not).
Has this been fixed yet? I.e. can we rely on accurate wait() and sleep()?
The linked msg was showing wait(1, port) takes at least 15ms on ARM platform (and that, as he pointed out, is 50% of time interval available per frame at 30fps)

It has been over a year and currently doco for roMessagePort.WaitMessage() and wait() and sleep() makes no qualifications, so one would imply precision and accuracy are under 1ms (i.e. you get what you ask for).

If on the other hand that was never addressed and is here to stay, can we get statement what’s the resolution/granularity in those functions work and update the documentation?

The bugs filed on sleep() and wait() were never closed, but a workaround was posted:

No wait:

msg = port.GetMessage()
if type(msg) = "roUniversalControlEvent" then
<act on message>
end if

if you need an accurate timer, you could use roTimeSpan

timer=createobject("rotimespan")
timer.mark()
while true
    if timer.totalmilliseconds() >= 10 then
        msg = port.GetMessage()
        timer.mark()
        if type(msg) = "roUniversalControlEvent" then
            <act on message>
        end if
    end if
end while
  • Joel

And while it could be mentioned elsewhere, the “Event loops” section of the Component Reference does refer to this.

–Mark

“RokuMarkn” wrote:
And while it could be mentioned elsewhere, the “Event loops” section of the Component Reference does refer to this.Where?
It is not that i posted yesterday before doing homework first - I read that section too and there was nothing mentioning wait granularity. The only thing i saw is:
… the screen may need to be updated with new animation frames even if no buttons are pressed or other events occur. One way to deal with this is to use a timeout as the first parameter of the call to wait:
msg = wait(5, port)
This waits for a message, but if no message is received within 5 milliseconds, the wait returns and msg is set to ‘invalid’. When feasible, this is a simple approach.

However, an approach that usually offers more predictable performance is to use ifMessagePort.GetMessage instead of wait. This is because GetMessage will return immediately if no message is available, while the actual amount of time before a timed wait returns can vary depending on various factors.
It says if you ask for 5ms, you get 5ms - that seems pretty clear stated, not 15ms or “no less than 5ms”. Did you mean the “the actual amount of time before a timed wait returns can vary depending on various factors” part? That is so veiled, so crafty if it was supposed to mean “never use wait(N>0)”.

To repeat the question: can we get clarification what’s the resolution/granularity in those functions?
There must be some resolution you can state, even if it is “least common denominator” kind (e.g. if 1ms for MIPS and 15ms for ARM, could be “resolution no worse than multiples of 15ms”).

I can rephrase the question in practical terms, if that helps: say for which of the following the real wait will be within 10% margin from the requested interval?

  1. wait(1000, p)

  2. wait(300, p)

  3. wait(100, p)

  4. wait(30, p)

  5. wait(10, p)

  6. wait(3, p)
    Seems clear if i ask for 3ms wait, i won’t get it +/-10% - and if i ask for 1000ms, i will get it (give or take 100ms). So the cut-off line is somewhere in-between but at which point?

This is a bug that is specific to the Roku2 3100x 3050x and 2400x hardware models and is, as far as I’m aware, not an issue on any other platform including the Roku legacy devices. Due to an instability, the high resolution timer on the device is not used for Wait() and Sleep() on these devices, which introduces some variability into the amount of time that is actually waited or slept.

You can time the actual wait time to find out for yourself if it is accurate:

timer=createobject("roTimeSpan")
timer.mark()
wait(3,port)
print timer.totalmilliseconds()

  • Joel

FWIW, I’ve seen a “Wait(1, port)” take anywhere from 1ms to as much as 20ms (possibly even higher), so my guess is that it’s dependent on a number of factors that can’t be definitively quantified into a percentage.

“TheEndless” wrote:
FWIW, I’ve seen a “Wait(1, port)” take anywhere from 1ms to as much as 20ms (possibly even higher), so my guess is that it’s dependent on a number of factors that can’t be definitively quantified into a percentage.
You misunderstood the question.
The example you are giving only shows that 1ms wait cannot be trusted within 10% variation. And i already said i don’t imagine 3ms can be trusted, so no news there.

Won’t you think 1000ms wait will be correct give or take 100ms and that is not “dependent on a number of factors”?
There are some values above which this is the case. I asked which are they - and even gave MCQ to pick

“EnTerr” wrote:

“TheEndless” wrote:
FWIW, I’ve seen a “Wait(1, port)” take anywhere from 1ms to as much as 20ms (possibly even higher), so my guess is that it’s dependent on a number of factors that can’t be definitively quantified into a percentage.
You misunderstood the question.
The example you are giving only shows that 1ms wait cannot be trusted within 10% variation. And i already said i don’t imagine 3ms can be trusted, so no news there.

Won’t you think 1000ms wait will be correct give or take 100ms and that is not “dependent on a number of factors”?
There are some values above which this is the case. I asked which are they - and even gave MCQ to pick
I’m still not sure I understand the question, but I just wrote up a simple test that loops through each Wait() 100 times returning the average time, the lowest time and the highest time for each. I ran it three times and got the following results:

------ 1st Run ------
Wait(1, port)         Average: 10.18    Shortest: 8     Longest: 20
Wait(3, port)         Average: 10.19    Shortest: 10    Longest: 19
Wait(10, port)        Average: 19.99    Shortest: 19    Longest: 21
Wait(30, port)        Average: 39.99    Shortest: 39    Longest: 41
Wait(100, port)       Average: 109.99   Shortest: 109   Longest: 110
Wait(300, port)       Average: 309.99   Shortest: 309   Longest: 311
Wait(1000, port)      Average: 1009.99  Shortest: 1009  Longest: 1011

------ 2nd Run ------
Wait(1, port)         Average: 10.23    Shortest: 8     Longest: 22
Wait(3, port)         Average: 10.19    Shortest: 10    Longest: 19
Wait(10, port)        Average: 19.99    Shortest: 19    Longest: 21
Wait(30, port)        Average: 39.99    Shortest: 39    Longest: 41
Wait(100, port)       Average: 109.99   Shortest: 109   Longest: 110
Wait(300, port)       Average: 309.99   Shortest: 309   Longest: 310
Wait(1000, port)      Average: 1009.99  Shortest: 1009  Longest: 1011

------ 3rd Run ------
Wait(1, port)         Average: 10.16    Shortest: 9     Longest: 20
Wait(3, port)         Average: 10.09    Shortest: 10    Longest: 19
Wait(10, port)        Average: 19.99    Shortest: 19    Longest: 21
Wait(30, port)        Average: 39.99    Shortest: 39    Longest: 40
Wait(100, port)       Average: 110.09   Shortest: 108   Longest: 122
Wait(300, port)       Average: 309.99   Shortest: 309   Longest: 311
Wait(1000, port)      Average: 1009.99  Shortest: 1009  Longest: 1011

I’m not sure if that tells you what you want to know, but it looks like you can pretty much count on 10ms being the lowest you can go, and a roughly, fairly consistent, 10ms overage for everything above that.