EmbeddedRelated.com
Forums

Sync to Android frame rate

Started by John Speth May 17, 2017
Hi Folks (and pardon me if I'm not on topic)-

I'm looking for a way to synchronize some code activity to the Android 
display frame rate. It's a short bit of code that will simply set the 
color of a small display region, nothing more. Is there some sort of 
method or hook that I can exploit for this purpose?

I can use a timer running at very fast intervals successfully but the 
rendering appears to suffer from aliasing with the frame rate. For 
example, my frame rate is 60 Hz so if I set the timer interval to 1/60 
seconds, the appearance is non-uniform. I can't set the timer to exactly 
16.666 msec and even if I could, I'd still see aliasing.

Thanks - JJS

> I'm looking for a way to synchronize some code activity to the Android > display frame rate. It's a short bit of code that will simply set the > color of a small display region, nothing more. Is there some sort of > method or hook that I can exploit for this purpose?
I'll answer my own question, partially that is. It appears one solution is to use the Choreographer class which provides a way to hook a callback function into the frame rate. Below is the code. It executes but the timing is sloppy. I can time the calls to doFrame() using System.nanoTime(). A little testing shows me the timing of calls to doFrame() is not uniform (ranging from 12 msec to 20 msec, expecting about 16 msec). The callback argument is rock steady (about 16 msec) which makes me think it's a value that is computed at initialization time. It's a solution but it's not doing what I wanted because the callback is not timing precisely enough. Still seeking advice, thank you. JJS /////////////////////////////////////////////////////////////// private FrameCallback frameCallback = null; private boolean frameCallbackPending = false; public void armVSyncHandler() { if(!frameCallbackPending) { frameCallbackPending = true; if(frameCallback == null) { frameCallback = new FrameCallback() { @Override public void doFrame(long frameTimeNanos) { frameCallbackPending = false; // Do some work here armVSyncHandler(); } }; } Choreographer.getInstance().postFrameCallback(frameCallback); } }
On 5/18/2017 2:59 PM, John Speth wrote:
>> I'm looking for a way to synchronize some code activity to the Android >> display frame rate. It's a short bit of code that will simply set the >> color of a small display region, nothing more. Is there some sort of >> method or hook that I can exploit for this purpose? > > I'll answer my own question, partially that is. It appears one solution > is to use the Choreographer class which provides a way to hook a > callback function into the frame rate. Below is the code. It executes > but the timing is sloppy. > > I can time the calls to doFrame() using System.nanoTime(). A little > testing shows me the timing of calls to doFrame() is not uniform > (ranging from 12 msec to 20 msec, expecting about 16 msec). The > callback argument is rock steady (about 16 msec) which makes me think > it's a value that is computed at initialization time. > > It's a solution but it's not doing what I wanted because the callback is > not timing precisely enough. Still seeking advice, thank you.
I know nothing about Android, but it seems to me there should be a graphics library that provides this sort of functionality. I would think your code would provide a buffer of data to be presented to the screen and a graphics call would hand it to the graphic processor which in turn copies that buffer in a highly synchronized manner. Trying to run user code synchronized to the frame update would be difficult to say the least. -- Rick C
rickman <gnuarm@gmail.com> wrote:
> > I know nothing about Android, but it seems to me there should be a > graphics library that provides this sort of functionality. I would > think your code would provide a buffer of data to be presented to the > screen and a graphics call would hand it to the graphic processor which > in turn copies that buffer in a highly synchronized manner.
There is, it's called SurfaceFlinger. Though you might want to use higher levels of the graphics stack because you may need further layers of compositing (eg controls on top of the image): https://source.android.com/devices/graphics/architecture Theo
On 5/19/2017 1:28 PM, Theo Markettos wrote:
> rickman <gnuarm@gmail.com> wrote: >> >> I know nothing about Android, but it seems to me there should be a >> graphics library that provides this sort of functionality. I would >> think your code would provide a buffer of data to be presented to the >> screen and a graphics call would hand it to the graphic processor which >> in turn copies that buffer in a highly synchronized manner. > > There is, it's called SurfaceFlinger. > Though you might want to use higher levels of the graphics stack because you > may need further layers of compositing (eg controls on top of the image): > https://source.android.com/devices/graphics/architecture
Looks right, but complicated. I didn't see anything that would provide the synchronization the OP is looking for but I can't believe it wouldn't be there. That would be required for glitch-less display updates which we know happens. -- Rick C
On 5/19/2017 10:28 AM, Theo Markettos wrote:
> rickman <gnuarm@gmail.com> wrote: >> >> I know nothing about Android, but it seems to me there should be a >> graphics library that provides this sort of functionality. I would >> think your code would provide a buffer of data to be presented to the >> screen and a graphics call would hand it to the graphic processor which >> in turn copies that buffer in a highly synchronized manner. > > There is, it's called SurfaceFlinger. > Though you might want to use higher levels of the graphics stack because you > may need further layers of compositing (eg controls on top of the image): > https://source.android.com/devices/graphics/architecture > > Theo >
Thanks, Theo. That looks like it's worth some experimentation. JJS
On 5/18/2017 11:59 AM, John Speth wrote:
>> I'm looking for a way to synchronize some code activity to the Android >> display frame rate. It's a short bit of code that will simply set the >> color of a small display region, nothing more. Is there some sort of >> method or hook that I can exploit for this purpose? > > I'll answer my own question, partially that is. It appears one solution > is to use the Choreographer class which provides a way to hook a > callback function into the frame rate. Below is the code. It executes > but the timing is sloppy. > > I can time the calls to doFrame() using System.nanoTime(). A little > testing shows me the timing of calls to doFrame() is not uniform > (ranging from 12 msec to 20 msec, expecting about 16 msec). The > callback argument is rock steady (about 16 msec) which makes me think > it's a value that is computed at initialization time. > > It's a solution but it's not doing what I wanted because the callback is > not timing precisely enough. Still seeking advice, thank you. > > JJS > > /////////////////////////////////////////////////////////////// > > private FrameCallback frameCallback = null; > private boolean frameCallbackPending = false; > > public void armVSyncHandler() { > if(!frameCallbackPending) { > frameCallbackPending = true; > if(frameCallback == null) > { > frameCallback = new FrameCallback() { > @Override > public void doFrame(long frameTimeNanos) { > frameCallbackPending = false; > > // Do some work here > > armVSyncHandler(); > } > }; > } > Choreographer.getInstance().postFrameCallback(frameCallback); > } > }
Update: I ran this code on a newer and probably faster phone (Samsung Galaxy Grand Prime). It seems to work like I wanted (no aliasing). I conclude the original phone (ZTE X752C) was way short of compute capacity. JJS
John Speth <johnspeth@yahoo.com> wrote:
> Update: I ran this code on a newer and probably faster phone (Samsung > Galaxy Grand Prime). It seems to work like I wanted (no aliasing). I > conclude the original phone (ZTE X752C) was way short of compute capacity.
If all you're doing is filling the screen with colour and you need to buy a faster phone, it feels something is wrong. For one thing, if that is the intended application (rather than a reduced test case of some other application) you should be using the GPU to do it and take basically no CPU time. Theo
On 5/22/2017 3:00 AM, Theo Markettos wrote:
> John Speth <johnspeth@yahoo.com> wrote: >> Update: I ran this code on a newer and probably faster phone (Samsung >> Galaxy Grand Prime). It seems to work like I wanted (no aliasing). I >> conclude the original phone (ZTE X752C) was way short of compute capacity. > > If all you're doing is filling the screen with colour and you need to buy a > faster phone, it feels something is wrong. > > For one thing, if that is the intended application (rather than a reduced > test case of some other application) you should be using the GPU to do it > and take basically no CPU time.
You're right, Theo. The application is a custom device that mates to a phone display and needs to receive signals, phone to custom device. Communication is one way and contains very little data (a few bytes per message). I think I can signal a photo-transistor in the custom device by switching a region of the screen as the comm channel. I'm weighing the trade-off of going deep and stepping around the Android graphics SW or playing nicely with it. The alternative is a costlier but much more reliable BLE comm. JJS
John Speth <johnspeth@yahoo.com> wrote:
> You're right, Theo. The application is a custom device that mates to a > phone display and needs to receive signals, phone to custom device. > Communication is one way and contains very little data (a few bytes per > message). I think I can signal a photo-transistor in the custom device > by switching a region of the screen as the comm channel. I'm weighing > the trade-off of going deep and stepping around the Android graphics SW > or playing nicely with it. The alternative is a costlier but much more > reliable BLE comm.
I'd have thought you make two buffers, one white the other black. Then you alternately tell it to composite one or other. You'll likely get a one-frame lag but, unless your phone is utterly ancient (< Android 4.0), the GPU will render it for you. Think of it as 'playing a 60Hz movie' but with only two images to choose from, that you never change pixels inside. If you're trying to colour in pixels from Java it's going to be a lot slower - because each one has to reach down the graphics stack, and that's all CPU side. Theo