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=en
package 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);
}

Reply via email to