Problem in DSA Frame buffer, Flickering during ringing
| Tue, 2007-01-16 17:15 | |
|
I am using Direct Screen Access API and displaying a bitmap from file through Frame Buffer. I am copying the bitmap to the screen using Mem::Copy. And I am displaying the this bitmap (Full Screen) when a call is made( i.e dialling ) or for an incoming call. The problems are:- 1. The bitmap color is distorted( bad color). My bitmap file has 24 bit color and my testing phone is 16 bit. How could i convert the color to display it's original one. 2. When the phone rings or there is a dial call my program brings the frame buffer bitmap to the full screen, but for some times the display is flickering with background dialog. After some time of flickering it's okay. What is the solution to this so that i can see a non-flickering image. I am a very new bee to symbian. Could anybody throw his kind light to this problem ? Any help ? Please .... Tushar Bhattacharyya |
|






Forum posts: 1232
The 16 bit color is on the standard format often called "565". This means of the 16 bits, the 5 most significant bits is red, the next 6 is green, and the last 5 is blue.
You need to convert each of your 24bit pixels (that have 8 bits per color channel) to this 16 bit pixel format.
Just take the most significant bits from each color channel and put it together should be good enough.
Best would be to do this once, to a new buffer, and throw away the old. Then use Mem::Copy for displaying this new buffer.
2.
The flickering is because you and the window server tries to draw to the screen at the same time.
My guess is the call dialog has some animation or such, therefore redrawing itself a few times.
And I assume you have some kind of loop displaying your image over and over...
As far as I understand, you are trying to draw this fullscreen image "on top" of the dialog, and you want it to "hide" the dialog.
This could be tricky to achive...
One way to hide a window is to put a window over it. Preferably the same window you connect to DSA.
The window needs to be part of a window group with a lower (or was it higher?
I'm not sure this is possible though, the call dialog is displayed by a system service that puts its window group at a very high priority.
Don't know if it is possible to specify your window to be "on top" of this.
Wouldn't supprice me if they had stopped it, since hideing the call dialog could be used for malicious intent.
Another sollution might be to use DirectScreenBitmap, but this is also tricky, and I can't guarantee it will work either in practice...
Sorry to be bearer of bad news, but this is a very hard problem to solve with the public API.
Forum posts: 45
I would first thank you for your helpful reply. But again I am facing problem in accessing the bits per channel. Could you help me how to shift and retrieve the most significant bit and load in my offscreen bitmap buffer?
And for the 2nd problem you catch me right that I am redrawing the screen using a timer. My timer has a time interval of exactly 1/64 sec i.e. 15625 microsec ( I am trying to match the screen refresh rate).
I am using DSA to draw the bitmap on top of any window application. And it is doing so with some flickers. So I am now sure that my program can bypass ( ? or may be not bypassing but drawing direct to screen frame) the window server. Please advice how can I proceed.
Thanking you,
Tushar
Tushar Bhattacharyya
Forum posts: 1232
Its slower, but compatible and fewer lines of code.
Something like this: (note.. Not tested code, just wrote it here quickly, not sure it even compiles, but something like this:)
{
//construction
CFbsBitmap *bmp16bit = new (ELeave) CFbsBitmap();
CleanupStack::PushL(bmp16bit);
User::LeaveIfError(bmp16bit.Create(aOrigBmp->SizeInPixels(),EColor64K)); //specifying 16 bit color format
CFbsBitmapDevice* bmpdev = CFbsBitmapDevice::NewL(bmp16bit);
CleanupStack::PushL(bmpdev);
CFbsBitGc* bmpgc = new (ELeave) CFbsBitGc();
CleanupStack::PushL(bmpgc);
//drawing
bmpgc->Activate(bmpdev);
bmpgc->DrawBitmap(TPoint(0,0),aOrigBmp);
//cleanup
CleanupStack::PopAndDestroy(2); //pop and destroy bmpgc and bmpdev
CleanupStack::Pop() //just pop the bmp (remove this line to make the function LC instead of L)
return bmp16bit;
}
I can write some more about DSA later
Forum posts: 45
Thank you so much for your quick reply. I will make it a try.
Thanks,
Tushar
Tushar Bhattacharyya
Forum posts: 21
I m trying to play the bitmap using directScreenAccess captured through CCamera::StartViewFinderBitmapL.
But i m facing the problem that it is playing the frame only when
some window appears in front of it like menu.
If anyone know the issue then pls. let
me know.
Thanks in advance!!!!!!!!!!!
Forum posts: 1232
Maybe you only start and stop your session on the events.
The first Start you have to call yourself.
But hard to say without the code. There is a ton of ways to mess up your DSA handling.
---
General on DSA:
Yes, you can always draw to the framebuffer. DSA doesn't really give you this, since it is always available.
What DSA is for, is for _access_control_ to the framebuffer.
That is, its used to be able to peacefully share the framebuffer with the window server.
Without DSA you can still draw to the framebuffer, but you will draw over stuff the wserv draws and the other way around, producing among other things flicker.
What DSA does, is you tell the wserv "I want to be responsible for filling this window" and the wserv will then never draw any visible area of this window, but assume you did it.
It will also, through the DSA api, tell you what region of the screen this window is visible in.
So to use DSA properly in your case, you have to put a window "on top" of everything else.
Search on this forum for examples on how to create a window and window group with an on top priority.
Forum posts: 45
I have tried on your following code :-
Something like this: (note.. Not tested code, just wrote it here quickly, not sure it even compiles, but something like this:)
Code:
CFbsBitmap* Create16bitVersionL(CFbsBitmap* aOrigBmp)
{
//construction
CFbsBitmap *bmp16bit = new (ELeave) CFbsBitmap();
CleanupStack::PushL(bmp16bit);
User::LeaveIfError(bmp16bit.Create(aOrigBmp->SizeInPixels(),EColor64K)); //specifying 16 bit color format
CFbsBitmapDevice* bmpdev = CFbsBitmapDevice::NewL(bmp16bit);
CleanupStack::PushL(bmpdev);
CFbsBitGc* bmpgc = new (ELeave) CFbsBitGc();
CleanupStack::PushL(bmpgc);
//drawing
bmpgc->Activate(bmpdev);
bmpgc->DrawBitmap(TPoint(0,0),aOrigBmp);
//cleanup
CleanupStack::PopAndDestroy(2); //pop and destroy bmpgc and bmpdev
CleanupStack::Pop() //just pop the bmp (remove this line to make the function LC instead of L)
return bmp16bit;
}
............ Thanks a lot for your code.
And it's displaying perfectly (Color is OK) when it run as a stand-alone. But the bitmap window is not displaying during call dialing (when calling.. dialog appeared)and looks it is running in the background.
The problem may be because of using of drawing method through bitmap graphics context. So now the problem is -
1. I am not able to use Graphics context to draw bitmap ( as it is not appearing during phone dialing), though is it giving me the right color.
2. I am not getting the right color though I am still able to see the bitmap display with flickers.
Could you let me know why am i getting this bad color ? one thing I understand that if i use graphics context ( for drawing or blitting bitmap) then it is doing the color conversion itself but not when Mem::Copy because the raw data is send directly to frame buffer without any color conversion.
My question is, I am using 24 bit bitmap. How to convert it to show it's original color to my 16 bit phone. I have found one DSA example through frame buffer on SDK example called "DrcScrAcc" . I stopped it's rendering to show the fixed bitmap. And after i done it I faced the problem --- color is distorted.
Thank you for your time. Please help...
Thanks,
Tushar
Tushar Bhattacharyya
Forum posts: 1232
Yes, this is exactly why you get bad colors. The pixel format of your bitmap did not match the pixel format of your screen.
The DrawBitmap function does the color conversion in my example code.
My thought was that you would use my code snippet to convert your bitmap into the right format.
Then use this new bitmap and display it with DSA as you did with your old.
This will not solve flicker though, but the color problem.
To solve flicker, you have to prevent the window server from drawing to the same area as you do.
The only public way I know of to do that, is to use DSA and connect that to an "on top" window, and then display this window on top of everything, including the dialog.
Forum posts: 45
Search on this forum for examples on how to create a window and window group with an on top priority.
The only public way I know of to do that, is to use DSA and connect that to an "on top" window, and then display this window on top of everything, including the dialog.
Thanks a lot Alh,
I found the required code to set a window on top of any window, by searching in this forum. And in this regards I must again thank you to insist me searching about the window priority. The usefull link is http://forum.newlc.com/index.php/topic,6163.0.html
I was trying to display my window when there is a out or in call. Now my window is on top of everything during dialing. Now my target is to show this top window only when line status changes to dialing or ringing, otherwise not.
To do the above thing I think I can create two views, one which will listen to call and when the call comes it will active the 2nd view. But the problem I am have is : how to use the phone class ( this class's performance is ok). Because from the phone class's RunL how to activate the 2nd view? I am confuse how to design the program. You gave me a lot of information already to come here, please help me ...
Any information is helpful.
Thanking you ,
Tushar
Tushar Bhattacharyya
Forum posts: 45
I am now able to activate the view2 from phone observer's runl. So during ringing/dialing my second view comes in the top of everything.
But..........
I am not able to activate/show the previous view (view1) when the call state state changes to idle/unknown from RunL of the phone observer, because phone observer is created from view1, so that it is able to call View1::HandleCommandL( ....
activateLocalView ( view2)) . And the activate command for view1 is in class view2, so here is the problem.... I could not able to get the view2 object reference from phoneobserver's runL. I know i have to change the program design and have to relocate phone observer some where else to access both views reference... but how ?
Please suggest if you have any idea to share....
Thanks,
Tushar
Tushar Bhattacharyya
Forum posts: 1232
Much easier to answer the more technical questions
It usually helps me to draw some pretty boxes on paper with lines and arrows showing dependencies (also known as UML if you like standards)
Basicly, you need to arrange your classes in a sensible way, and make sure that every class that needs it get a pointer to any other classes they have dependencies on, during construction.
I can't really help you there, you just have to think through different alternatives until you find what is most suitable for you...
maybe you should put the phone observer not in any of the views, but in appui maybe, and then it might be easier to see how it can have references to the views it needs.
Just a suggestion to consider, don't know if it is good for you
The appui is a nice place though, because you can easily reach it from anywhere in your app, by casteing the pointer returned by CCoeEnv::Static()->AppUi() to your appui subclass.
Forum posts: 45
Hello Alh,
Wooooooow !! Thanks a lot ! I made it working. Now I can activate two views respectively when necessary. I have put the phone observer in Appui and created the views from phone class. And after some work i made it to run.
Thanks , your suggestions are really fantastic !
Tushar Bhattacharyya
Forum posts: 45
The old problem comes at the end of my program !
I was setting a window on top of everything using CEikonEnv::Static()->RootWin().SetOrdinalPriority(0, ECoeWinPriorityAlwaysAtFront ) to show one of my two views;
The code works fine. But then I am not able to send the application at background. I have used CEikonEnv::Static()->RootWin().SetOrdinalPosition (-1, ECoeWinPriorityNeverAtFront); to send it back with the other view but not worked. My window stays on the front.
And also if I set the view2 as default with ordinal priority ECoeWinPriorityNeverAtFront, my application never comes at front
Please help how to use those two methods.... any idea would be helpful for me.
Thanks in Advance.
Tushar
Tushar Bhattacharyya
Forum posts: 45
I have found why it occurs. The view is not changing because the code to activate the another view is not reachable. I am activating the 1st view when call status changes to dialling or ringing and activating 2nd view when checking the call status is hangingup...
But there is a KErrOverFlow in iStatus of the activa object (i found this after a long work) and the code to activate the 2nd view is then not reachable as :-
if(iStatus.Int() == KErrNone)
the above checking fails.
I searched SDK and webs but i dont find anything why this overflow occurs in my RunL.
Could anyone let me know why I'm getting this error?
Tushar Bhattacharyya
Forum posts: 45
Isn't there anybody there who knows something about why KErrOverFlow occurs in a RunL(). Any idea ?
Tushar Bhattacharyya