@Override
  public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    Log.d(TAG, "onSurfaceCreated");

    // We're starting up or coming back.  Either way we've got a new EGLContext that will
    // need to be shared with the video encoder, so figure out if a recording is already
    // in progress.
    mRecordingEnabled = mVideoEncoder.isRecording();
    if (mRecordingEnabled) {
      mRecordingStatus = RECORDING_RESUMED;
    } else {
      mRecordingStatus = RECORDING_OFF;
    }

    // Set up the texture blitter that will be used for on-screen display.  This
    // is *not* applied to the recording, because that uses a separate shader.
    mFullScreen = new FullFrameRect(new Texture2dProgram(Texture2dProgram.ProgramType.TEXTURE_EXT));

    mTextureId = mFullScreen.createTextureObject();

    // Create a SurfaceTexture, with an external texture, in this EGL context.  We don't
    // have a Looper in this thread -- GLSurfaceView doesn't create one -- so the frame
    // available messages will arrive on the main thread.
    mSurfaceTexture = new SurfaceTexture(mTextureId);

    // Tell the UI thread to enable the camera preview.
    mCameraHandler.sendMessage(
        mCameraHandler.obtainMessage(
            CameraCaptureActivity.CameraHandler.MSG_SET_SURFACE_TEXTURE, mSurfaceTexture));
  }
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_camera_capture);

    File outputFile = new File(Environment.getExternalStorageDirectory(), "camera-test.mp4");
    TextView fileText = (TextView) findViewById(R.id.cameraOutputFile_text);
    fileText.setText(outputFile.toString());

    Spinner spinner = (Spinner) findViewById(R.id.cameraFilter_spinner);
    ArrayAdapter<CharSequence> adapter =
        ArrayAdapter.createFromResource(
            this, R.array.cameraFilterNames, android.R.layout.simple_spinner_item);
    adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
    // Apply the adapter to the spinner.
    spinner.setAdapter(adapter);
    spinner.setOnItemSelectedListener(this);

    // Define a handler that receives camera-control messages from other threads.  All calls
    // to Camera must be made on the same thread.  Note we create this before the renderer
    // thread, so we know the fully-constructed object will be visible.
    mCameraHandler = new CameraHandler(this);

    mRecordingEnabled = sVideoEncoder.isRecording();

    // Configure the GLSurfaceView.  This will start the Renderer thread, with an
    // appropriate EGL context.
    mGLView = (GLSurfaceView) findViewById(R.id.cameraPreview_surfaceView);
    mGLView.setEGLContextClientVersion(2); // select GLES 2.0
    mRenderer = new CameraSurfaceRenderer(mCameraHandler, sVideoEncoder, outputFile);
    mGLView.setRenderer(mRenderer);
    mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);

    Log.d(TAG, "onCreate complete: " + this);
  }