Problem in the combination of textureView and OpenGL - android

Currently I am trying to work with both textureView and OpenGL, and my target is to read the buffer from SurfaceTexture. After lots of searching, I found grafika, but fail to find a suitable example that using textureview.(and, for some reason I have to use textureView)
What I try was that I created a texture and tried to set the textureView to use it:
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(null);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.activity_textureview);
displayTextureView=(TextureView) findViewById(R.id.camera_textureview);
mEglCore = new EglCore(null, EglCore.FLAG_RECORDABLE);
mOffscreenSurface=new OffscreenSurface(mEglCore,VIDEO_WIDTH,VIDEO_HEIGHT);
mOffscreenSurface.makeCurrent();
mFullFrameBlit = new FullFrameRect(
new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));
mTextureId = mFullFrameBlit.createTextureObject();
mCameraTexture = new SurfaceTexture(false);
mCameraTexture.attachToGLContext(mTextureId);
displayTextureView.setSurfaceTextureListener(mSurfaceTextureListener);
displayTextureView.setSurfaceTexture(mCameraTexture);
mHandler = new MainHandler(this);
Initialized=true;
}
But then it gitves me the error:
GLConsumer is already attached to a context
I have also found this, but after I tried the method described here what I got from glReadPixels was totally black, so I guess the surfaceTexture must be attached to GLcontext to read the pixels.
Can anybody give me some help?

you should refer to this
https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/ContinuousCaptureActivity.java
this example use surfaceView , you just need to replace to textureView.
the 386 row:"mDisplaySurface = new WindowSurface(mEglCore, holder.getSurface(), false);"
just replace holder.getSurface() with surfacetexture from textureView.
And there is a method to read buffer
https://github.com/google/grafika/blob/master/app/src/main/java/com/android/grafika/gles/EglSurfaceBase.java
look at the saveFrame method.

Related

How to constantly take pictures in Android Camera2?

I'm working on an Android project where I have to repeatedly take photos and process them with a facial recognition API. I realize that I have to use camera2's methods (either setRepeatingRequest or setRepeatingBurst), but these methods only take a photo once every 5 seconds or so. I was wondering how I would change this to take a picture at least twice every second without lag. Is this even possible? If not, what would you recommend I use to do this?
private final ImageReader.OnImageAvailableListener mOnImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
#Override
public void onImageAvailable(ImageReader reader) {
try (Image image = reader.acquireNextImage()) {
Image.Plane[] planes = image.getPlanes();
if (planes.length > 0) {
ByteBuffer buffer = planes[0].getBuffer();
byte[] data = new byte[buffer.remaining()];
buffer.get(data);
mCallback.onPictureTaken(data);
}
}
}
};
This may help you,here is the use of Camera2.
https://github.com/google/cameraview
https://github.com/google/cameraview/blob/master/library/src/main/api21/com/google/android/cameraview/Camera2.java

Rajawali Carboard OBJ File

I just started using Rajawali and the Cardboard SDK (the integration that you can find in Rajawali’s repository). Based on the examples provided (loaders) in the repository and following the instructions to set up a new project I have created an example where I create a sphere (and attach a texture to it) and load an OBJ file, the odd thing is that I can actually see the sphere and the texture but not the OBJ object. I created a similar example where the difference just resides on the class that I’m extending, in one example I extend the RajawaliRender class (in this one I see the OBJ file) and in the other I extend the RajawaliCarboardRender. I would really appreciate if you can give a hand or provide me an example because I’m stuck and I have tried everything I can think of.
This is the content of my initScene method in both examples:
public void initScene(){
directionalLight = new DirectionalLight(1f, .2f, -1.0f);
directionalLight.setColor(1.0f, 1.0f, 1.0f);
directionalLight.setPower(2);
getCurrentScene().addLight(directionalLight);
Material material = new Material();
material.enableLighting(true);
material.setDiffuseMethod(new DiffuseMethod.Lambert());
material.setColor(0);
Texture earthTexture = new Texture("Earth", R.drawable.earthtruecolor_nasa_big);
try{
material.addTexture(earthTexture);
} catch (ATexture.TextureException error){
Log.d("DEBUG", "TEXTURE ERROR");
}
earthSphere = new Sphere(1, 24, 24);
earthSphere.setMaterial(material);
getCurrentScene().addChild(earthSphere);
getCurrentCamera().setZ(14.2f);
final LoaderOBJ loaderOBJ = new LoaderOBJ(mContext.getResources(), mTextureManager, R.raw.multiobjects_obj);
loadModel(loaderOBJ, this, R.raw.multiobjects_obj);
}

Grafika TextureMovieEncoder

I have recently been modifying Grafika's TextureMovieEncoder to create a recording of what I displayed onscreen: two Sprite2ds which are overlapping. Using the CameraCaptureActivity example as a reference point, I effectively ported what I created for my rendering thread into the TextureMovieEncoder but the output is jagged lines across the screen. I think I understand what's wrong, but I don't know how to fix it:
Some code:
private void prepareEncoder(EGLContext sharedContext, int width, int height, int bitRate,
File outputFile) {
try {
mVideoEncoder = new VideoEncoderCore(width, height, bitRate, outputFile);
} catch (IOException ioe) {
throw new RuntimeException(ioe);
}
mEglCore = new EglCore(sharedContext, EglCore.FLAG_RECORDABLE);
mInputWindowSurface = new WindowSurface(mEglCore, mVideoEncoder.getInputSurface(), true);
mInputWindowSurface.makeCurrent();
textureProgram = new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT);
backgroundDrawable = new Drawable2d(Drawable2d.Prefab.RECTANGLE);
backgroundRect = new Sprite2d(backgroundDrawable);
frontDrawable = new Drawable2d(Drawable2d.Prefab.RECTANGLE);
frontRect = new Sprite2d(frontDrawable);
backgroundRect.setTexture(backTextureId);
frontRect.setTexture(frontTextureId);
updateGeometry();
}
private void handleFrameAvailable(Transform transform, long timestampNanos) {
if (VERBOSE) Log.d(TAG, "handleFrameAvailable tr=" + transform);
mVideoEncoder.drainEncoder(false);
backgroundRect.draw(textureProgram, transform.movieMatrix);
frontRect.draw(textureProgram, transform.cameraMatrix);
mInputWindowSurface.setPresentationTime(timestampNanos);
mInputWindowSurface.swapBuffers();
}
I think the problem comes down to my lack of understanding of how to establish the right projection onto the WindowSurface for the VideoEncoder. In the Grafika example, FullFrameRect is used, which is easier since you can just use the identity matrix to stretch a given texture to the surface area. However, since I want to create the overlapping effect, I needed to use Sprite2d. Is the problem the shared EGLContext? Do I need to create a new one so that I can set the viewport to match the WindowSurface size? A bit lost on where to go from here.
Turns out the functionality of the code above was fine. The problem was the interaction between the TextureEncoder and the calling parent.
I was initializing the member variables backTextureId and frontTextureId after prepareEncoder and it was therefore recording garbage data into the output.

Android : java.lang.NoSuchField Exception for mSurface while trying use surface from native

I want to feed buffer of the surface from Native code. So I get the surface from SurfaceView's SurfaceHolder's getSurface method. Now all I want is to use it from the native to feed buffer to render image. I have included SurfaceClinger/Surface.h. But when I try to get mSurface property, it throws error saying java.lang.NoSuchFieldException for mSurface.
Any suggestion in this regard will be helpful.
code snippet:
Surface mSurface;
SurfaceHolder mSurfaceHolder;
mSurface = mSurfaceHolder.getSurface();
try{
class myClass = mSurface.getClass();
String fieldName = "mSurface";
Field field = myClass.getDeclaredField(fieldName);
field.setAccesssible(true);
int surfacePtr = field.getInt(mSurface);
nativeInterface.DrawOnSurface(surfacePtr);
}
catch(Exception ex){}
Thanks.
From gingerbread onwards, the field name is different. By replacing fieldname from 'mSurface' to 'mNativeSurface' the problem is solved. for froyo and below 'mSurface' will work.

when load Assets?

what is the best way?
1) make a method:
Assets.loadAll()
that load all the texture used in the game, and call this method in the splashScreen (so only one time in all the activity life)
OR
2) make one method for each screen (ie. Assets.loadMainMenu, Assets.loadGameScreen, etc..) and call it in the show() of any screen? (and in the hide() call the Assets.disposeMainMenuAssets, Assets.disposeGameScreenAssets, etc etc..)
NOTE: the 2) is slower than the first but in in the first if i block the phone (with classical phisical button) and after go back to the app, the texture disappear (it doesn't happen if i press the 'home' button... but if i lock the phone yes.... and the strange thing is that in libGdx 9.6 if i lock the phone the textures don't disappear, but with libGdx 9.7 this append..)
If it's 5MB's of assets I say just load them on the splash screen. That way there will be little to no "load" time between screen switching. Method 1 is the best for this.
Create a class called Assets. In this have a static method called "load", like so
public class Assets {
private static Texture tex;
public static TextureRegion tree,cloud1,cloud2,cloud3,rock,platform,playerStanding,
rocket, rocketShadow, moon, star;
public static SpriteAnimation playerMoving;
public static void load(){
tex = new Texture(Gdx.files.internal("data/Graphics.png"));
tex.setFilter(TextureFilter.Linear, TextureFilter.Linear);
tree = new TextureRegion(tex, 0,0,246,226);
cloud1 = new TextureRegion(tex, 246,0,225,92);
cloud2 = new TextureRegion(tex, 358,197,88,84);
cloud3 = new TextureRegion(tex, 0,226,105,64);
rock = new TextureRegion(tex, 246,197,112,90);
platform = new TextureRegion(tex, 246,92,193,105);
tex = new Texture(Gdx.files.internal("data/Graphics2.png"));
tex.setFilter(TextureFilter.Linear, TextureFilter.Linear);
playerMoving = new SpriteAnimation(new TextureRegion(tex,0,0,458,555), 4, 5, 0.01f);
playerStanding = new TextureRegion(tex,0,0,112,110);
tex = new Texture(Gdx.files.internal("data/Graphics3.png"));
tex.setFilter(TextureFilter.Linear, TextureFilter.Linear);
rocket = new TextureRegion(tex,0,218,119,201);
rocketShadow = new TextureRegion(tex,0,0,138,218);
tex = new Texture(Gdx.files.internal("data/Graphics4.png"));
tex.setFilter(TextureFilter.Linear, TextureFilter.Linear);
moon = new TextureRegion(tex,0,0,410,382);
star = new TextureRegion(tex,0,382,123,123);
}
public static void dispose(){
tex.dispose();
}
}
(This is just an example from my game. The names aren't important, just the methods)
On your splash screen you can just call Assets.load(); and all your assets will be loaded!
Then you want to use an asset you can just make a call to it via Assets.whatever (which being static is fine)
Hope this helps!

Categories

Resources