I've been updating my app which runs a glsurface on top of a camera preview.
It works fine with the camera preview running into a surfaceview
but when I the camera preview to use a texture (which looks like a cleaner
way of doing it with and gives more flexibility) it does not work.
With a TextureView ,the camera preview works fine until I add the
glsurfaceview, at which point all the transparent bits go black.
If I use a SurfaceView then the camera preview shows through the transarent
bits just fine.
I have a very simple view hierarchy: here are the 2 versions:
version that works
android.widget.RelativeLayout
android.widget.TextView
com.iain.camera.CameraView (1) => extends SurfaceView
com.iain.graphicbase.GlSurface (1) => extends GLSurfaceView
version that blanks the camera preview
android.widget.RelativeLayout
android.widget.TextView
com.iain.camera.CameraView (1) => extends TextureView
com.iain.graphicbase.GlSurface (1) => extends GLSurfaceView
rather hacked about code with working version active and textureview
version commented out attached
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=enpackage com.iain.camera;
import java.io.IOException;
import java.util.EnumSet;
import java.util.List;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.hardware.Camera.CameraInfo;
import android.hardware.Camera.Size;
import android.util.AttributeSet;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import android.view.WindowManager;
import com.iain.ui.PootableElement;
import com.iain.utils.LogAreas;
import com.iain.utils.LoggerFrag;
import com.iain.utils.LoggerTag;
import com.iain.utils.LoggerFrag.LogLevels;
//public class CameraView extends TextureView implements TextureView.SurfaceTextureListener,
public class CameraView extends SurfaceView implements SurfaceHolder.Callback,
LoggerTag, PootableElement {
public CameraView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
LoggerFrag.addEntry(logarea, loglevel, this, "constructor1", null);
constructorSetup(context);
}
public CameraView(Context context, AttributeSet attrs) {
super(context, attrs);
LoggerFrag.addEntry(logarea, loglevel, this, "constructor2", null);
constructorSetup(context);
}
public CameraView(Context context) {
super(context);
LoggerFrag.addEntry(logarea, loglevel, this, "constructor3", null);
constructorSetup(context);
}
//The first rear facing camera
int defaultCameraId = -1;
Camera currentCam = null;
boolean orientIsLandscape;
Size previewSize;
List<Size> camPreviewSizes;
int lastSurfaceWidth = 0;
int lastSurfaceHeight = 0;
// SurfaceTexture surfTexture;
SurfaceHolder sholder;
Camera.Parameters lastparams = null;
int maxExpComp = 0;
int minExpComp = 0;
int expcomp = 0;
private void constructorSetup(Context c) {
int camCount = Camera.getNumberOfCameras();
CameraInfo camInfo = new CameraInfo();
for (int i = 0; i < camCount; i++) {
Camera.getCameraInfo(i, camInfo);
if (camInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
defaultCameraId= i;
}
}
if (LoggerFrag.checkActive(logarea, loglevel)) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "constructorSetup", "default camera is " + defaultCameraId);
}
//TODO
// setSurfaceTextureListener(this);
// Install a SurfaceHolder.Callback so we get notified when the
// underlying surface is created and destroyed.
sholder = getHolder();
sholder.addCallback(this);
// setHasOptionsMenu(mNumberOfCameras > 1);
if (LoggerFrag.checkActive(logarea, loglevel)) {
LoggerFrag.addCallExit(logarea, loglevel, this, "constructorSetup", null);
}
}
@Override
public void onPViewConnected(SharedPreferences sp) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "onPViewConnected", "connect to camera " + defaultCameraId);
// Open the default i.e. the first rear facing camera.
// View sb = this.getActivity().findViewById(R.id.compx);
// if (sb instanceof SeekBar) {
// LoggerFrag.addCallEntry(myloglev, EnumSet.of(LogLevels.guiEvents), this, "onResume", "seekbar found");
// SeekBar x = (SeekBar)sb;
// x.setOnSeekBarChangeListener(this);
// }
LoggerFrag.addCallExit(logarea, loglevel, this, "onResume", "camera is "
+ ((currentCam == null) ? "NULL" : "OK"));
}
public void setCamera(Camera camera) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "setCamera",
((camera == null) ? "NO CAMERA" : "with camera " + defaultCameraId));
if (currentCam != null) {
// currentCam.stopPreview();
currentCam.release();
LoggerFrag.addEntry(logarea, loglevel, this, "setCamera", "camera released");
}
currentCam = camera;
if (currentCam != null) {
lastparams = currentCam.getParameters();
camPreviewSizes = lastparams.getSupportedPreviewSizes();
Camera.Size previewSize;
if (lastSurfaceWidth > 0 && camPreviewSizes != null) {
if (orientIsLandscape) {
previewSize = getOptimalPreviewSize(camPreviewSizes, lastSurfaceWidth, lastSurfaceHeight);
} else {
previewSize = getOptimalPreviewSize(camPreviewSizes, lastSurfaceHeight, lastSurfaceWidth);
}
LoggerFrag.addEntry(logarea, loglevel, this, "setCamera"
, "calculate preview" + previewSize.width + " / " + previewSize.height);
} else {
previewSize = lastparams.getPreviewSize();
LoggerFrag.addEntry(logarea, loglevel, this, "setCamera"
, "default preview" + previewSize.width + " / " + previewSize.height);
}
lastparams.setPreviewSize(lastSurfaceWidth, lastSurfaceHeight);
// setLayoutParams(new RelativeLayout.LayoutParams(
// previewSize.width, previewSize.height));
LoggerFrag.addEntry(logarea, loglevel, this, "setCamera", ((orientIsLandscape)?"landscape":"portrait") + " setCamera"
+ "requesting " + previewSize.width + " / " + previewSize.height);
Display display = ((WindowManager)getContext().getSystemService(Context.WINDOW_SERVICE))
.getDefaultDisplay();
int rotation = display.getRotation();
int degrees = 0;
switch (rotation) {
case Surface.ROTATION_0: degrees = 0; break;
case Surface.ROTATION_90: degrees = 90; break;
case Surface.ROTATION_180: degrees = 180; break;
case Surface.ROTATION_270: degrees = 270; break;
}
int result;
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(defaultCameraId, info);
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
result = (info.orientation + degrees) % 360;
result = (360 - result) % 360; // compensate the mirror
} else { // back-facing
result = (info.orientation - degrees + 360) % 360;
}
currentCam.setDisplayOrientation(result);
LoggerFrag.addEntry(logarea, loglevel, this, "setCamera", "preview set to " + previewSize.width
+ " / " + previewSize.height + " disp orient: " + rotation + " camorient: " + info.orientation
+ " camera disp orient set to " + result);
minExpComp = lastparams.getMinExposureCompensation();
maxExpComp = lastparams.getMaxExposureCompensation();
// if (surfTexture != null) {
try {
currentCam.setParameters(lastparams);
currentCam.setPreviewDisplay(sholder);
//TODO currentCam.setPreviewTexture(surfTexture);
currentCam.startPreview();
} catch (IOException ioe) {
LoggerFrag.addEntry(logarea, loglevel, this, "setCamera"
, "EEK starting preview: " + ioe.getMessage());
}
// }
//TODO String ecv = PootableElManager.getSharedPref().getString("camprefexposurecomp", "0");
// expcomp = 0;
// try {
// float ecf = Float.parseFloat(ecv);
// setExposureComp(ecf);
// } catch (NumberFormatException ne) {
//
// }
//TODO redundant?
// requestLayout();
} else {
this.lastSurfaceWidth = 0;
lastSurfaceHeight = 0;
}
LoggerFrag.addCallExit(logarea, EnumSet.of(LogLevels.obEvents), this, "setCamera",
((currentCam == null) ? "NO CAMERA" : "with camera "));
}
@Override
public void onPViewDisconnected(SharedPreferences.Editor spe) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "onPViewDisconnected", "camera is "
+ ((currentCam == null) ? "NULL" : "OK"));
setCamera(null);
LoggerFrag.addCallExit(logarea, loglevel, this, "onPViewDisconnected", null);
}
/********************************************************************************************
* TextureView surface handling
*/
/* @Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "onSurfaceTextureAvailable"
, "size: " + width + " / " + height);
surfTexture = surface;
lastSurfaceWidth = width;
lastSurfaceHeight = height;
orientIsLandscape = width > height;
setCamera(Camera.open(defaultCameraId));
LoggerFrag.addCallExit(logarea, loglevel, this, "onSurfaceTextureAvailable",null);
} */
public void surfaceCreated(SurfaceHolder holder) {
// The Surface has been created, acquire the camera and tell it where
// to draw.
LoggerFrag.addCallEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "surfaceCreated",
"with holder " + holder + " with " + holder.getSurface());
setCamera(Camera.open(defaultCameraId));
LoggerFrag.addCallExit(logarea, EnumSet.of(LogLevels.guiEvents), this, "surfaceCreated", null);
}
/* @Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "onSurfaceTextureSizeChanged"
, "size: " + width + " / " + height);
if (lastSurfaceWidth != width || lastSurfaceHeight != height) {
lastSurfaceWidth = width;
lastSurfaceHeight = height;
orientIsLandscape = width > height;
if (currentCam != null) {
setCamera(null);
}
setCamera(Camera.open(defaultCameraId));
}
LoggerFrag.addCallExit(logarea, loglevel, this, "onSurfaceTextureSizeChanged", null);
} */
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// Now that the size is known, set up the camera parameters and begin
// the preview.
LoggerFrag.addCallEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "surfaceChanged",
"with holder " + holder + " with " + holder.getSurface());
if (lastSurfaceWidth != w || lastSurfaceHeight != h) {
lastSurfaceWidth = w;
lastSurfaceHeight = h;
orientIsLandscape = w > h;
if (currentCam != null) {
setCamera(null);
}
setCamera(Camera.open(defaultCameraId));
}
LoggerFrag.addCallExit(logarea, EnumSet.of(LogLevels.guiEvents), this, "surfaceChanged",
"w=" + w + " h=" + h);
}
/* @Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
setCamera(null);
return true;
} */
/* public void onSurfaceTextureUpdated(SurfaceTexture surface) {
// Invoked every time there's a new Camera preview frame
} */
public void surfaceDestroyed(SurfaceHolder holder) {
// Surface will be destroyed when we return, so stop the preview.
LoggerFrag.addCallEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "surfaceDestroyed",
"with holder " + holder + " with " + holder.getSurface() + ((currentCam == null)?" no camera":" camera present"));
if (currentCam != null) {
currentCam.stopPreview();
}
LoggerFrag.addCallExit(logarea, EnumSet.of(LogLevels.guiEvents), this, "surfaceDestroyed", null);
}
/***************************************************************************************
* measure and layout
*/
@Override
protected void onMeasure(int wms, int hms) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "onMeasure",
"given " + MeasureSpec.toString(wms) + " / " + MeasureSpec.toString(hms));
if (( MeasureSpec.getMode(wms) == MeasureSpec.EXACTLY
|| MeasureSpec.getMode(wms) == MeasureSpec.AT_MOST)
&& (MeasureSpec.getMode(hms) == MeasureSpec.EXACTLY
|| MeasureSpec.getMode(hms) == MeasureSpec.AT_MOST)) {
lastSurfaceWidth = MeasureSpec.getSize(wms);
lastSurfaceHeight = MeasureSpec.getSize(hms);
setMeasuredDimension(lastSurfaceWidth, lastSurfaceHeight);
orientIsLandscape = lastSurfaceWidth > lastSurfaceHeight;
LoggerFrag.addCallExit(logarea, loglevel, this, "onMeasure",
"set: " + lastSurfaceWidth + " / " + lastSurfaceHeight);
} else {
super.onMeasure(wms,hms);
LoggerFrag.addCallExit(logarea, loglevel, this, "onMeasure",
"given " + MeasureSpec.toString(wms) + " / " + MeasureSpec.toString(hms)
+ " gave: " + getWidth() + " / " + getHeight());
}
}
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
LoggerFrag.addEntry(logarea, loglevel, this, "onLayout", left + " <-> " + right + " / " + top + " # " + bottom);
super.onLayout(changed, left, top, right, bottom);
}
private Size getOptimalPreviewSize(List<Size> sizes, int w, int h) {
LoggerFrag.addCallEntry(logarea, loglevel, this, "getOptimalPreviewSize", null);
int amaxw = w;
int amaxh = h;
int missedby = Integer.MAX_VALUE;
int bestindex = -1;
boolean looking = true;
int spsi = 0;
Size ts = camPreviewSizes.get(0);
while (looking) {
ts = camPreviewSizes.get(spsi);
if (amaxw >= ts.width && amaxh >= ts.height) {
int newmiss = amaxw - ts.width + amaxh - ts.height;
if (newmiss == 0) {
bestindex = spsi;
looking = false;
} else {
if (newmiss < missedby) {
bestindex = spsi;
missedby = newmiss;
}
if ((spsi+1) < camPreviewSizes.size()) {
spsi++;
} else {
looking=false;
}
}
} else {
if ((spsi+1) < camPreviewSizes.size()) {
spsi++;
} else {
looking=false;
}
}
}
if (bestindex == -1) {
ts = camPreviewSizes.get(camPreviewSizes.size()-1);
} else {
ts = camPreviewSizes.get(bestindex);
}
LoggerFrag.addCallExit(logarea, loglevel, this, "getOptimalPreviewSize",
"using entry " + bestindex + " (" + ts.width + "/" + ts.height + ")");
return ts;
}
/*************************************************************************
* settings bits
*/
/* public void updateSettingsTest() {
Parameters campam = currentCam.getParameters();
int curec = campam.getExposureCompensation();
curec++;
if (curec > campam.getMaxExposureCompensation()) {
curec = campam.getMinExposureCompensation();
}
campam.setExposureCompensation(curec);
mCamera.setParameters(campam);
LoggerFrag.addEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "updateSettingsTest", "Exposure compensation now " + curec);
} */
private void setExposureComp(float nec) {
if (lastparams != null) {
float ecstep = lastparams.getExposureCompensationStep();
int newec = Math.round(nec / ecstep);
if (newec < lastparams.getMinExposureCompensation()) {
newec = lastparams.getMinExposureCompensation();
}
if (newec > lastparams.getMaxExposureCompensation()) {
newec = lastparams.getMaxExposureCompensation();
}
expcomp = newec;
lastparams.setExposureCompensation(newec);
LoggerFrag.addEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "setExposureComp", "ask " + nec
+ " use " + newec);
if (currentCam != null) {
currentCam.setParameters(lastparams);
}
}
}
/*
@Override
public boolean onPreferenceChange(Preference pref, Object newValue) {
LoggerFrag.addEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "onPreferenceChange",
"using value " + newValue.getClass() + " with pref " + pref.getKey());
if (lastparams != null && newValue instanceof String) {
float nv = 0;
try {
nv = Float.parseFloat((String)newValue);
} catch (NumberFormatException ne) {
LoggerFrag.addEntry(logarea, EnumSet.of(LogLevels.guiEvents), this, "onPreferenceChange"
, newValue + " is not a float");
return false;
}
setExposureComp(nv);
return true;
}
return false;
} */
/***************************************************************************
* housekeeping
*/
static int ltindex = 0;
final int ltag = ++ltindex;
public int getLTid() {
return ltag;
}
private static EnumSet<LogAreas.Areas> logarea = EnumSet.of(LogAreas.Areas.camelem);
private static EnumSet<LogLevels> loglevel = EnumSet.of(LogLevels.camerasetup);
}