2

I am trying to duplicate the drawing process on a TextureView into other TextureViews. The main goal being to be able to create a "wall" of one same video being played from one instance of a MediaPlayer attached to a TextureView (I've got that part done). This is first for performance issues since using multiple MediaPlayer instances could have catastrophic performances, and also to be sure that all the videos are on sync with each other.

Thank you for your answers/suggestions.

Edit: Overriding onDraw() doesn't work because TextureView uses OpenGL to draw on its surface. If anyone has some insight on how I can duplicate or override that behavior. Other suggestions are of course welcome!

genpfault
  • 51,148
  • 11
  • 85
  • 139
Hey'Youssef
  • 285
  • 4
  • 15

1 Answers1

1

Originally, I thought you might be lucky and this might be a simple case of overriding the onDraw(Canvas) method of the TextureView to do something like this:

final int xTiles = 5;
final int yTiles = 5;

@Override
public void onDraw(Canvas canvas){
    int widthPerTile = canvas.getWidth() / xTiles;
    int heightPerTile = canvas.getHeight() / yTiles;
    float widthScale = widthPerTile / (float) canvas.getWidth();
    float heightScale = heightPerTile / (float) canvas.getHeight();

    for(int x = 0; x < xTiles; x++){
        for(int y = 0; y < yTiles; y++){
            canvas.save();
            canvas.translate(x * widthPerTile, y * heightPerTile);
            canvas.scale(widthScale, heightScale);
            super.onDraw(canvas);
            canvas.restore();
        }
    }
}

Then you will only need one CustomTextureView taking up the whole screen and it'll look like a lot, because it will be drawing itself lots of times.

However, this is not how the TextureView works. The TextureView instead has a dummy onDraw(Canvas) method and instead uses its own draw(Canvas) method which is final and therefore cannot be overriden. The TextureView is using OpenGL to draw the frames from the camera, and it's quite complicated to inject yourself in that process, although it seems posssible following examples like can be found being discussed here. This is an advanced topic indeed and probably a bit much for a Saturday morning for me to write a succinct answer for.

But, I did manage to hack something together quickly that you might be able to take advantage of and run with, although it has some obvious issues with regards to memory and framerate:

public class CopyCatTextureView extends View {
    TextureView textureViewToCopy;

    public CopyCatTextureView(Context context) {
        super(context);
    }

    public void setTextureViewToCopy(TextureView view){
        this.textureViewToCopy = view;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if(textureViewToCopy != null){
            textureViewToCopy.draw(canvas);
        }
    }
}

If you have a grid of a single TextureView and the rest being these CopyCatTextureViews, you can call setTextureViewToCopy(TextureView) on each of the copy cats to point to the single TextureView and then simply call invalidate() on each of the copy cats whenever you want a frame update. Obviously this is not ideal, but it's quick and certainly will work if you just want a single frame.

Hope this helps. Best of luck.

(Variable edited)

Spettacolo83
  • 282
  • 4
  • 10
DanielLaneDC
  • 1,731
  • 11
  • 9
  • I don't believe this'll work. `TextureView` doesn't draw like regular `View`s, and I think it makes `onDraw()` `final` anyway, IIRC. – Mike M. Feb 25 '17 at 00:50
  • You're right, it is final. Let me see what I can do. – DanielLaneDC Feb 25 '17 at 01:05
  • That's exaclty how I tried to do it at first, then realize that the onDraw() is just a dummy and that all the drawing is done on OpenGL. I have also tried a similar approach like the "hack" you've suggested but without any luck, I only get a black frame on my custom view. I was wondering if anyone who had maybe worked on cardboard applications or OpenGL on Android could give me some insight on this issue. Thank you DanielLaneDC for the attempt though! – Hey'Youssef Feb 25 '17 at 18:11
  • No worries Hey'Youssef. For the record, I was able to copy the TextureView onto the custom view I posted, I didn't get black, but I would have to manage the framerate myself. I will be looking forward to seeing what someone with OpenGL experience says myself! – DanielLaneDC Feb 26 '17 at 02:22
  • doesn't work. even though textureViewToCopy.draw(canvas); is called the texture remains blank. I'd imagine that even if it could work performance would be extremely low (depending on resolution of course). Anyway thanks for the answer – vir us Jun 09 '18 at 13:52