Searched for 3 whole days and lots of related information found, but none is accurate enough and due to my lack of knowledge in computer graphic. I just dicide to ask a question here.
To make it clear,
1) I have FrameLayout
2) I added a TextureView to it
3) I set the LayoutParams to the FrameLayout to a kind of squre shape thus somehow the TextureView is resized according to that too, becoming a square, which is not very confusing
4) Everything between the Camera Previewing work and TextureView displaying work works fine BUT
4!) As we all know just like in SurfaceView days. If we force drawing Camera preview data into an not-quite-suit-the-camera-preview-size-view, the final result just get stretched.
4.) I mean I know how to resize the FrameLayout/TextureView to make it 4:3/~16:9 (Landscap or Portrait) programmely, but I need it to be sqaure, really, and not stretched of course
5?) I think I should preprocess the SurfaceTexture data via openGL thins. (I think this is quite obvious but I'm not so sure so if you have a completely different way to acheive the result. It will also be appreciated.
5) About the preAsking jobs. I got plenty of sample of doing this but only with a plain SurfaceView or GLSurfaceView. Since I am not so familar with original openGL programming. I suffered when I try to morph the code into my project
5+) No, I have to use TextureView. If you doubt the reason that is because Google transfered their Camera sample into using TextureView so I do think I have to learn dealing with TextureView+openGL combo. Anyway TextureView comes on to the stage just to make it simpler to bahave like and only life a View and cooperate with light-weighted openGL processing without a scratch isn't it
6) I really cannot port those online samples to mine. I have trouble even in attatching openGL context with the SurfaceTexture (omg)
7) Yes I have a skeleton-like code structure and everything works except for the drawFrame impl. What the hell should I put into it
The Activity
public class MainActivity extends ActionBarActivity {
private ImageView imageView;
private TextView textView;
private Camera mCamera;
private MirrorScope mScope;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.qrCode);
textView = (TextView) findViewById(R.id.title);
// Create an instance of Camera
mCamera = getCameraInstance();
// Create our Preview view and set it as the content of our activity.
mScope = new MirrorScope(this, mCamera);
mScope.setSurfaceTextureListener(mScope);
FrameLayout scopeDrawer = (FrameLayout) findViewById(R.id.camera_preview);
scopeDrawer.setLayoutParams(new LinearLayout.LayoutParams(700,700));
scopeDrawer.addView(mScope);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/** Check if this device has a camera */
private boolean checkCameraHardware(Context context) {
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){
// this device has a camera
return true;
} else {
// no camera on this device
return false;
}
}
/** A safe way to get an instance of the Camera object. */
public static Camera getCameraInstance(){
Camera c = null;
try {
c = Camera.open(); // attempt to get a Camera instance
}
catch (Exception e){
// Camera is not available (in use or does not exist)
}
return c; // returns null if camera is unavailable
}
}
The TextureView
public class MirrorScope extends TextureView implements TextureView.SurfaceTextureListener {
private Camera mCamera;
private Context mContext;
private TextureView mTextureView;
private ScopeGLThread renderer;
public MirrorScope(Context context , Camera camera) {
super(context);
mCamera = camera;
// TODO Auto-generated constructor stub
}
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width,
int height) {
// mCamera = Camera.open();
try {
mCamera.setPreviewTexture(surface);
mCamera.startPreview();
} catch (IOException ioe) {
// Something bad happened
}
renderer = new ScopeGLThread(surface);
renderer.start();
}
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width,
int height) {
// Ignored, Camera does all the work for us
}
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
renderer = null;
mCamera.stopPreview();
mCamera.release();
return true;
}
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
//renderer.notify();
}
}
The openGL Thread
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.egl.EGLSurface;
import android.graphics.SurfaceTexture;
import android.opengl.EGL14;
import android.util.Log;
public class ScopeGLThread extends Thread {
SurfaceTexture mSurface;
EGL10 mEgl;
EGLDisplay mEglDisplay;
EGLConfig mEglConfig;
EGLContext mEglContext;
EGLSurface mEglSurface;
public ScopeGLThread(SurfaceTexture surface) {
mSurface = surface;
}
@Override
public void run() {
initGL();
while(true) {
drawFrame();
Log.v("omg","oooomg"); //this do print thus I think the main loop is kidda work-ful
//wait(); //however this hurts even with try/catch bloack it kills my app
}
}
private void initGL() {
mEgl = (EGL10)EGLContext.getEGL();
mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int versions[] = new int[2];
mEgl.eglInitialize(mEglDisplay, versions);
int configsCount[] = new int[1];
EGLConfig configs[] = new EGLConfig[1];
int configSpec[] = new int[]{
EGL10.EGL_RENDERABLE_TYPE,
EGL14.EGL_OPENGL_ES2_BIT,
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_DEPTH_SIZE, 0,
EGL10.EGL_STENCIL_SIZE, 0,
EGL10.EGL_NONE };
mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount);
mEglConfig = configs[0];
int contextSpec[] = new int[]{
EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
EGL10.EGL_NONE };
mEglContext = mEgl.eglCreateContext(mEglDisplay, mEglConfig, EGL10.EGL_NO_CONTEXT, contextSpec);
mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface, null);
mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
}
private void drawFrame() {
//mSurface.attachToGLContext(1);
//mSurface.detachFromGLContext();
//mEgl..glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
//mSurface.updateTexImage();
// everything I put here kills everything ( and some deleted other kind of trying)
}
}
how should I get a gl instance? I find it confused when some of the sample uses gl (from nowhere... or a argument), others using EGL14.blahblah things. I mean... omg I don't really know openGL and the khronos package reference on Android.com is VOID...)
Tutorial of solving the exact problem step-by-step is really needed but if you explain it clearly in text form that'll also be great. When I need square I think we can make it the simplest by just cropping the left-top squre of Camera preview data. That would be very helpful. And yes I may need to add some kind of filter function so don't hack the square-problem. I insist doing this via openGL, quite.
BTW, Google samples are not accessible due to the network situation of my Country. I can but do not very satisfying preasking-searching-work and I apology for that.