Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
829 views
in Technique[技术] by (71.8m points)

multithreading - Android thread controlling multiple texture views causes strange flickering

I am trying to use a single thread to render three separate TextureView's off the UI thread using canvas lock/unlock. The problem observed is the consistent flickering of each of the Texture Views being drawn, with the flicker consisting of a DIFFERENT TextureView's frame. So for example, I draw frames A,B and C in that order. Frame C will appear fine, however frames A and B will flicker with occasional instances of Frame C, and frame A will occasionally flicker with instances of Frame B.

I have read through the documentation describing Android Core Graphics, and have a fairly good understanding of how android's frame buffering system works. In a nutshell, my suspicion is that I am performing lockCanvas/unlockCanvasAndPost call's too quickly in succession, and that the framebuffer is unable to complete my request and simply draws the previous (incorrect) frame instead.

I've tried several things to resolve this issue. Attempting to use Choreographer to wait for VSYNC before continuing to call canvas helped, but as expected lowered my frame rate however the problem was still there. I've also tried an alternative render loop sans sleep command, with no difference in the observed phenomenon.

Essentially I am out of ideas on how to tackle this problem, and was hoping to get some outside input on it. Thanks in advance, code snippet is below:

Main render loop:

 while (running) {

        long now = System.nanoTime();
        long updateLength = now - lastLoopTime;
        lastLoopTime = now;
        float delta = updateLength / ((float)OPTIMAL_TIME.get());

        lastFpsTime += updateLength;
        fps++;

        if (lastFpsTime >= 1000000000)
        {
            Log.e(TAG, "(FPS Target: " + TARGET_FPS+ " ,FPS Actual: " + fps + ")");
            lastFpsTime = 0;
            fps = 0;
        }


        for (MyTextureView mtv : mItemList){
            if (!mtv.isLocked()) {
                mtv.doUpdate(delta);
                mtv.doRender();
            }
        }

        long sleepTime = (lastLoopTime-System.nanoTime() + OPTIMAL_TIME.get())/1000000;
        sleepTime = sleepTime < 0 ? 0 : sleepTime;

        try{
            Thread.sleep( sleepTime );
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }

    }

MyTextureView doRender() method:

public void doRender() {
    doubleBufferCanvas.drawPaint(Colors.BLACK);
    doDraw(doubleBufferCanvas); //draws content onto secondary canvas

        Canvas c = lockCanvas();
        c.drawPaint(Colors.BLACK);
        c.save();
        c.drawBitmap(dbbmp, 0, 0, null);
        c.restore();
        unlockCanvasAndPost(c);
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

I was able to find a workaround for this. (i dont observe this on android 5.0 and above).

Add a psuedo transparent view like below

            <View
                android:id="@+id/flicker_hack_view"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_alignParentBottom="true"
                android:layout_centerHorizontal="true"
                android:alpha="0.01"
                android:background="@color/black_12" />

which covers the entire activity wherever there is a textureView. the alpha should be set to 0.01 or a smaller value to make it seem invisible.

This workaround was based on my observation that when the two textureviews rendering videos overlap the flicker is not observed.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share

2.1m questions

2.1m answers

63 comments

56.6k users

...