Question

I made a video-recording app for the Google Glass. The app worked perfectly until Google release firmware XE19.1. I have another Google Glass with firmware XE18.11. The app still works on the Google Glass with XE18.11.

I get the following error:

07-30 15:39:32.273: V/MediaRecorder(17101): video.h264enc.profile is set to : 1
07-30 15:39:32.679: W/IMediaDeathNotifier(17101): media server died
07-30 15:39:32.679: W/CameraBase(17101): Camera service died!
07-30 15:39:32.679: W/CameraBase(17101): mediaserver's remote binder Camera object died
07-30 15:39:32.687: E/CameraManager(17101): Media Recorder error: what=100, extra=0
07-30 15:39:32.726: E/Camera(17101): Error 100

What i tried and did not work:

  • Tried MediaRecorder example from Google. only works with older firmware
  • Factory reset Google Glass
  • Tried with and without starting preview before recording. both work on older firmware
  • Changed SurfaceView to TextureView. both work on older firmware
  • Looked at changelog GDK XE19.1
  • Googled on error

It's strange because even the Google example doesn't work. This is the code after changing SurfaceView to TextureView:

public class CameraManager implements OnErrorListener
{
    private final static String TAG = CameraManager.class.getName();
    private final static int PREVIEW_SIZE_WIDTH = 640;
    private final static int PREVIEW_SIZE_HEIGHT = 360;

    private Activity mContext;
    private Camera mCamera;
    private TextureView mCameraPreview;
    private CameraListener mCameraListener;
    private MediaRecorder mMediaRecorder;
    private File mOutputVideoFile;
    private boolean mRecording;
    private boolean mTakingPicture;

    public CameraManager(Activity context, TextureView cameraPreview,
            CameraListener cameraListener)
    {
        mRecording = false;
        mTakingPicture = false;
        mContext = context;

        mCameraPreview = cameraPreview;
        mCameraListener = cameraListener;
    }

    public void startRecording(File outputVideoFile)
    {
        Log.d(TAG, "startRecording");

        mOutputVideoFile = outputVideoFile;
        new MediaPrepareTask().execute(null, null, null);
    }

    public void stopRecording()
    {
        Log.d(TAG, "stopRecording");

        mRecording = false;

        // stop the recording
        mMediaRecorder.stop();
        // if we are using MediaRecorder, release it first
        releaseMediaRecorder();
        // take camera access back from MediaRecorder
        mCamera.lock();
        // release the camera immediately on pause event
        releaseCamera();
    }

    public boolean isBusyRecording()
    {
        return mRecording;
    }

    public void takePicture(final TakePictureCallback pictureCallback)
    {
        if (isBusyRecording() && !mTakingPicture)
        {
            mTakingPicture = true;

            mCamera.takePicture(null, null, new PictureCallback()
            {
                @Override
                public void onPictureTaken(final byte[] pictureData, Camera camera)
                {
                    pictureCallback.onPictureTaken(pictureData);
                    mTakingPicture = false;
                }
            });
        }
    }

    @TargetApi(Build.VERSION_CODES.KITKAT)
    private boolean prepareVideoRecorder()
    {
        Log.d(TAG, "prepareVideoRecorder");

        // BEGIN_INCLUDE (configure_preview)
        mCamera = CameraHelper.getDefaultCameraInstance();

        // We need to make sure that our preview and recording video size are
        // supported by the
        // camera. Query camera to find all the sizes and choose the optimal
        // size given the
        // dimensions of our preview surface.
        Camera.Parameters parameters = mCamera.getParameters();
        List<Camera.Size> mSupportedPreviewSizes = parameters.getSupportedPreviewSizes();
        Camera.Size optimalSize = CameraHelper.getOptimalPreviewSize(mSupportedPreviewSizes,
                PREVIEW_SIZE_WIDTH, PREVIEW_SIZE_HEIGHT);

        // Use the same size for recording profile.
        CamcorderProfile profile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);
        profile.videoFrameWidth = optimalSize.width;
        profile.videoFrameHeight = optimalSize.height;

        // likewise for the camera object itself.
        parameters.setPreviewSize(profile.videoFrameWidth, profile.videoFrameHeight);
        mCamera.setParameters(parameters);
        try
        {
            // Requires API level 11+, For backward compatibility use {@link
            // setPreviewDisplay}
            // with {@link SurfaceView}
            mCamera.setPreviewTexture(mCameraPreview.getSurfaceTexture());
        }
        catch (IOException e)
        {
            Log.e(TAG, "Surface texture is unavailable or unsuitable" + e.getMessage());
            return false;
        }
        // END_INCLUDE (configure_preview)

        // BEGIN_INCLUDE (configure_media_recorder)
        mMediaRecorder = new MediaRecorder();
        mMediaRecorder.setOnErrorListener(this);

        // Step 1: Unlock and set camera to MediaRecorder
        mCamera.unlock();
        mMediaRecorder.setCamera(mCamera);

        // Step 2: Set sources
        mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);

        // Step 3: Set a CamcorderProfile (requires API Level 8 or higher)
        mMediaRecorder.setProfile(profile);

        // Step 4: Set output file
        mMediaRecorder.setOutputFile(mOutputVideoFile.toString());
        // END_INCLUDE (configure_media_recorder)

        // Step 5: Prepare configured MediaRecorder
        try
        {
            mMediaRecorder.prepare();
        }
        catch (IllegalStateException e)
        {
            Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder();
            return false;
        }
        catch (IOException e)
        {
            Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());
            releaseMediaRecorder();
            return false;
        }
        return true;
    }

    private void releaseMediaRecorder()
    {
        Log.d(TAG, "releaseMediaRecorder");

        if (mMediaRecorder != null)
        {
            // clear recorder configuration
            mMediaRecorder.reset();
            // release the recorder object
            mMediaRecorder.release();
            mMediaRecorder = null;
            // Lock camera for later use i.e taking it back from MediaRecorder.
            // MediaRecorder doesn't need it anymore and we will release it if
            // the activity pauses.
            mCamera.lock();
        }
    }

    private void releaseCamera()
    {
        Log.d(TAG, "releaseCamera");

        if (mCamera != null)
        {
            // release the camera for other applications
            mCamera.release();
            mCamera = null;
        }
    }

    /**
     * Asynchronous task for preparing the {@link android.media.MediaRecorder}
     * since it's a long blocking operation.
     */
    class MediaPrepareTask extends AsyncTask<Void, Void, Boolean>
    {
        @Override
        protected Boolean doInBackground(Void... voids)
        {
            Log.d(TAG, "MediaPrepareTask - doInBackground");

            // initialize video camera
            if (prepareVideoRecorder())
            {
                // Camera is available and unlocked, MediaRecorder is prepared,
                // now you can start recording
                mMediaRecorder.start();

                mRecording = true;
            }
            else
            {
                // prepare didn't work, release the camera
                releaseMediaRecorder();
                return false;
            }
            return true;
        }

        @Override
        protected void onPostExecute(Boolean result)
        {
            if (!result)
            {
                mContext.finish();
            }

            mCameraListener.onCameraRecording();
        }
    }

    @Override
    public void onError(MediaRecorder mr, int what, int extra)
    {
        Log.e(TAG, String.format("Media Recorder error: what=%d, extra=%d", what, extra));
    }
}

Thank you

Was it helpful?

Solution

Unfortunately, this is a known issue that is currently tracked in our issue tracker.

UPDATE: This issue has been fixed with the 20.1 update.

OTHER TIPS

Try setting the parameters.setRecordingHint(true); on the camera before starting the record process. This fixed the issue for me. See here for a complete example.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top