Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/181.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android-Camera2 api-MediaRecorder-为帧报告的输出缓冲区丢失_Android_Android Mediarecorder_Android Camera2 - Fatal编程技术网

Android-Camera2 api-MediaRecorder-为帧报告的输出缓冲区丢失

Android-Camera2 api-MediaRecorder-为帧报告的输出缓冲区丢失,android,android-mediarecorder,android-camera2,Android,Android Mediarecorder,Android Camera2,我有一个很大的问题,一些安卓设备和摄像头模块 这是我的CameraPresenter.java模块: public class CameraPresenter { public static final int SECOND_TICK = 1000; private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90; private static final int SENSOR_ORIENTATION_INVERSE_DEGRE

我有一个很大的问题,一些安卓设备和摄像头模块

这是我的CameraPresenter.java模块:

public class CameraPresenter {

public static final int SECOND_TICK = 1000;
private static final int SENSOR_ORIENTATION_DEFAULT_DEGREES = 90;
private static final int SENSOR_ORIENTATION_INVERSE_DEGREES = 270;
private static final SparseIntArray DEFAULT_ORIENTATIONS = new SparseIntArray();
private static final SparseIntArray INVERSE_ORIENTATIONS = new SparseIntArray();

static {
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_0, 90);
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_90, 0);
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_180, 270);
    DEFAULT_ORIENTATIONS.append(Surface.ROTATION_270, 180);
}

static {
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_0, 270);
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_90, 180);
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_180, 90);
    INVERSE_ORIENTATIONS.append(Surface.ROTATION_270, 0);
}

public static final int CAMERA_BACK = 0;
public static final int CAMERA_FRONT = 1;

private CustomTextureView mTextureView;
private CameraDevice mCameraDevice;
private CameraCaptureSession mPreviewSession;
private Size mPreviewSize;
private Size mVideoSize;
private MediaRecorder mMediaRecorder;
private MediaPlayer mMediaPlayer;
public boolean
        mIsRecordingVideo,
        mIsPlayingVideo,
        mIsAfterRecording = false;
private HandlerThread mBackgroundThread;
private Handler mBackgroundHandler;
private Semaphore mCameraOpenCloseLock = new Semaphore(1);
private Activity activity;
private Integer mSensorOrientation;
private String mOriginalVideoAbsolutePath,
        mCroppedVideoAbsolutePath,
        mFlipVideoAbsolutePath,
        mFinalVideoPath;
private String videoTime;
private Long videoTimeNumber;
private CaptureRequest.Builder mPreviewBuilder;

private Surface mRecorderSurface;
int cameraType = 1;

public CameraPresenter(Activity activity) {
    this.activity = activity;
}

public void setTextureView(CustomTextureView mTextureView) {
    this.mTextureView = mTextureView;
}

public void setCameraType(int cameraType) {
    this.cameraType = cameraType;
}

public int getCameraType() {
    return cameraType;
}

public boolean isRecordingVideo() {
    return mIsRecordingVideo;
}

public boolean isAfterRecording() {
    return mIsAfterRecording;
}

private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {

    @Override
    public void onOpened(CameraDevice cameraDevice) {
        mCameraDevice = cameraDevice;
        startPreview(false);
        mCameraOpenCloseLock.release();
        if (null != mTextureView) {
            configureTransform(mTextureView.getWidth(), mTextureView.getHeight());
        }
    }

    @Override
    public void onDisconnected(CameraDevice cameraDevice) {
        mCameraOpenCloseLock.release();
        cameraDevice.close();
        mCameraDevice = null;
    }

    @Override
    public void onError(CameraDevice cameraDevice, int error) {
        mCameraOpenCloseLock.release();
        cameraDevice.close();
        mCameraDevice = null;
    }

};


private static Size chooseVideoSize(Size[] choices) {
    for (Size size : choices) {
        if (size.getWidth() == size.getHeight() * 4 / 3 && size.getWidth() <= 1080) {
            return size;
        }
    }
    Log.e(AppConstants.TAG, "chooseVideoSize: Couldn't find any suitable video size");
    return choices[choices.length - 1];
}

/**
 * Given {@code choices} of {@code Size}s supported by a camera, chooses the smallest one whose
 * width and height are at least as large as the respective requested values, and whose aspect
 * ratio matches with the specified value.
 *
 * @param choices     The list of sizes that the camera supports for the intended output class
 * @param width       The minimum desired width
 * @param height      The minimum desired height
 * @param aspectRatio The aspect ratio
 * @return The optimal {@code Size}, or an arbitrary one if none were big enough
 */
private static Size chooseOptimalSize(Size[] choices, int width, int height, Size aspectRatio) {
    // Collect the supported resolutions that are at least as big as the preview Surface
    List<Size> bigEnough = new ArrayList<Size>();
    int w = aspectRatio.getWidth();
    int h = aspectRatio.getHeight();
    for (Size option : choices) {
        if (option.getHeight() == option.getWidth() * h / w &&
                option.getWidth() >= width && option.getHeight() >= height) {
            bigEnough.add(option);
        }
    }

    // Pick the smallest of those, assuming we found any
    if (bigEnough.size() > 0) {
        return Collections.min(bigEnough, new CompareSizesByArea());
    } else {
        Log.e(AppConstants.TAG, "chooseOptimalSize: Couldn't find any suitable preview size");
        return choices[0];
    }
}

public Long getVideoTimeNumber() {
    return videoTimeNumber;
}

public void startBackgroundThread() {
    mBackgroundThread = new HandlerThread("CameraBackground");
    mBackgroundThread.start();
    mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
}

public void stopBackgroundThread() {
    mBackgroundThread.quitSafely();
    try {
        mBackgroundThread.join();
        mBackgroundThread = null;
        mBackgroundHandler = null;
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

public void openCamera(int width, int height, int cameraType) {
    if (null == activity || activity.isFinishing()) {
        return;
    }
    mMediaPlayer = null;
    CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
    try {
        Log.d(AppConstants.TAG, "tryAcquire");
        if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
            throw new RuntimeException("Time out waiting to lock camera opening.");
        }
        this.cameraType = cameraType;
        String cameraId = manager.getCameraIdList()[cameraType];

        CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraId);
        StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
        mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION);
        mVideoSize = chooseVideoSize(map.getOutputSizes(MediaRecorder.class));
        mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                width, height, mVideoSize);

        int orientation = activity.getResources().getConfiguration().orientation;
        if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
            mTextureView.setAspectRatio(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        } else {
            mTextureView.setAspectRatio(mPreviewSize.getHeight(), mPreviewSize.getWidth());
        }
        Log.w(AppConstants.TAG, "WIDTH :" + width);
        Log.w(AppConstants.TAG, "HEIGHT :" + height);
        configureTransform(width, height);
        mMediaRecorder = new MediaRecorder();
        if (ActivityCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        manager.openCamera(cameraId, mStateCallback, null);
    } catch (CameraAccessException e) {
        Toast.makeText(activity, "Cannot access the camera.", Toast.LENGTH_SHORT).show();
        activity.finish();
    } catch (NullPointerException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted while trying to lock camera opening.");
    }
}

public void closeCamera() {
    try {
        mCameraOpenCloseLock.acquire();
        closePreviewSession();
        if (null != mCameraDevice) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
        if (null != mMediaRecorder) {
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
    } catch (InterruptedException e) {
        throw new RuntimeException("Interrupted while trying to lock camera closing.");
    } finally {
        mCameraOpenCloseLock.release();
    }
}

/**
 * Start the camera preview.
 */
private void startPreview(boolean recordAgain) {
    if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
        return;
    }
    try {
        if (!recordAgain)
            closePreviewSession();
        SurfaceTexture texture = mTextureView.getSurfaceTexture();
        assert texture != null;
        texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        Surface previewSurface = new Surface(texture);
        mPreviewBuilder.addTarget(previewSurface);
        mCameraDevice.createCaptureSession(Arrays.asList(previewSurface), new CameraCaptureSession.StateCallback() {

            @Override
            public void onConfigured(CameraCaptureSession cameraCaptureSession) {
                mPreviewSession = cameraCaptureSession;
                updatePreview();
            }

            @Override
            public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) {
                Log.w(AppConstants.TAG, "Camera failed....");
            }
        }, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

public void turnOnLight() throws CameraAccessException {
    mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_TORCH);
    mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
}

public void turnOffLight() throws CameraAccessException {
    mPreviewBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF);
    mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, null);
}

private void updatePreview() {
    if (null == mCameraDevice) {
        return;
    }
    try {
        setUpCaptureRequestBuilder(mPreviewBuilder);
        HandlerThread thread = new HandlerThread("CameraPreview");
        thread.start();
        mPreviewSession.setRepeatingRequest(mPreviewBuilder.build(), null, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    }
}

private void setUpCaptureRequestBuilder(CaptureRequest.Builder builder) {
    builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO);
}

/**
 * Configures the necessary {@link android.graphics.Matrix} transformation to `mTextureView`.
 * This method should not to be called until the camera preview size is determined in
 * openCamera, or until the size of `mTextureView` is fixed.
 *
 * @param viewWidth  The width of `mTextureView`
 * @param viewHeight The height of `mTextureView`
 */
public void configureTransform(int viewWidth, int viewHeight) {
    if (null == mTextureView || null == mPreviewSize || null == activity) {
        return;
    }
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    Matrix matrix = new Matrix();
    RectF viewRect = new RectF(0, 0, viewWidth, viewHeight);
    RectF bufferRect = new RectF(0, 0, mPreviewSize.getHeight(), mPreviewSize.getWidth());
    float centerX = viewRect.centerX();
    float centerY = viewRect.centerY();
    if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
        bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY());
        matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL);
        float scale = Math.max(
                (float) viewHeight / mPreviewSize.getHeight(),
                (float) viewWidth / mPreviewSize.getWidth());
        matrix.postScale(scale, scale, centerX, centerY);
        matrix.postRotate(90 * (rotation - 2), centerX, centerY);
    }
    mTextureView.setTransform(matrix);
}

private void setUpMediaRecorder(Activity activity) throws IOException {
    if (null == activity) {
        return;
    }
    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
    if (mOriginalVideoAbsolutePath == null || mOriginalVideoAbsolutePath.isEmpty()) {
        mOriginalVideoAbsolutePath = getOriginalVideoFilePath(activity);
    }
    mMediaRecorder.setOutputFile(mOriginalVideoAbsolutePath);
    mMediaRecorder.setVideoEncodingBitRate(1500000);
    mMediaRecorder.setMaxDuration(AppConstants.VIDEO_MAX_DURATION);
    mMediaRecorder.setVideoFrameRate(16);
    mMediaRecorder.setVideoSize(mVideoSize.getWidth(), mVideoSize.getHeight());
    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
    int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
    switch (mSensorOrientation) {
        case SENSOR_ORIENTATION_DEFAULT_DEGREES:
            mMediaRecorder.setOrientationHint(DEFAULT_ORIENTATIONS.get(rotation));
            break;
        case SENSOR_ORIENTATION_INVERSE_DEGREES:
            mMediaRecorder.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation));
            break;
    }
    mMediaRecorder.prepare();

}



private String getVideoTime() {
    Long videoCreationTime = System.currentTimeMillis();
    videoTimeNumber = videoCreationTime;
    videoTime = videoCreationTime.toString();
    return videoTime;
}

private String getFlippedVideoFilePath(Context context) {
    mFlipVideoAbsolutePath = context.getExternalFilesDir(null).getAbsolutePath() + "/"
            + videoTime + "flipped.mp4";
    return mFlipVideoAbsolutePath;
}

private String getFinalVideoFilePath(Context context) {
    return getFileDirectory(context).getAbsolutePath() + "/"
            + videoTime + ".mp4";
}


public boolean recordAgainAction() {
    startPreview(true);
    return true;
}

public void shutdownPlayingMovie(RecordActivity.PlayerManager playerManager) {
    mMediaPlayer.stop();
    mMediaPlayer.release();
    playerManager.onEndPlaying(true);
    mIsPlayingVideo = false;
}



private void deleteMovie(String path) {
    File file = new File(path);
    if (file.exists()) {
        if (file.delete()) {
            Log.d(AppConstants.TAG, "Success!! File deleted :" + path);
        } else {
            Log.d(AppConstants.TAG, "Failure... file not deleted :" + path);
        }
    }
}

public boolean isPlayingVideo() {
    return this.mIsPlayingVideo;
}

public void startRecordingVideo(final CountDownTimer countDownTimer) {
    if (null == mCameraDevice || !mTextureView.isAvailable() || null == mPreviewSize) {
        return;
    }
    try {
        closePreviewSession();
        setUpMediaRecorder(activity);
        SurfaceTexture texture = mTextureView.getSurfaceTexture();
        assert texture != null;
        texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());
        mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
        List<Surface> surfaces = new ArrayList<>();

        // Set up Surface for the camera preview
        Surface previewSurface = new Surface(texture);
        surfaces.add(previewSurface);
        mPreviewBuilder.addTarget(previewSurface);

        // Set up Surface for the MediaRecorder
        mRecorderSurface = mMediaRecorder.getSurface();
        surfaces.add(mRecorderSurface);
        mPreviewBuilder.addTarget(mRecorderSurface);
        // Start a capture session
        // Once the session starts, we can update the UI and start recording
        mCameraDevice.createCaptureSession(surfaces, new CameraCaptureSession.StateCallback() {

            @Override
            public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                mPreviewSession = cameraCaptureSession;
                updatePreview();
                activity.runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        // UI
                        countDownTimer.start();
                        mIsRecordingVideo = true;
                        // Start recording
                        mMediaRecorder.start();
                    }
                });
            }

            @Override
            public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                Log.w(AppConstants.TAG, "Camera failed....");
                if (null != activity) {
                    Toast.makeText(activity, "Failed", Toast.LENGTH_SHORT).show();
                }
            }
        }, mBackgroundHandler);
    } catch (CameraAccessException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

}

private void closePreviewSession() {
    if (mPreviewSession != null) {
        mPreviewSession.close();
        mPreviewSession = null;
    }
}

public void stopRecordingVideo(RecordingManager recordingManager, CountDownTimer countDownTimer, RenderManager renderManager) {
    stopRecorder();
    //closeCamera();
    countDownTimer.cancel();
    cropVideo(renderManager, recordingManager);
    Log.d(AppConstants.TAG, "Video saved: " + mOriginalVideoAbsolutePath);
}

public void stopRecorder() {
    mIsRecordingVideo = false;
    mIsAfterRecording = true;
    mMediaRecorder.stop();
}

public boolean ifVideoAlreadyPlayed() {
    return mMediaPlayer != null;
}


public void showRecordedVideo(CustomTextureView playTextureView, final RecordActivity.PlayerManager playerManager) {
    try {
        if (mMediaPlayer == null) {
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setSurface(new Surface(playTextureView.getSurfaceTexture()));
            if (cameraType == CAMERA_FRONT)
                mMediaPlayer.setDataSource(mCroppedVideoAbsolutePath);
            else
                mMediaPlayer.setDataSource(mCroppedVideoAbsolutePath);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
                @Override
                public void onCompletion(MediaPlayer mp) {
                    mMediaPlayer.stop();
                    playerManager.onEndPlaying(false);
                    playerManager.initMaxProgress(mp);
                    mIsPlayingVideo = false;
                }
            });
            mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    mMediaPlayer.start();
                    playerManager.initMovieDuration(mp);
                    mIsPlayingVideo = true;
                }
            });
            mMediaPlayer.prepareAsync();
        } else {
            mMediaPlayer.prepareAsync();
        }

    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (SecurityException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalStateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public void stopPlayer() {
    mMediaPlayer.stop();
}

/**
 * Compares two {@code Size}s based on their areas.
 */
static class CompareSizesByArea implements Comparator<Size> {

    @Override
    public int compare(Size lhs, Size rhs) {
        return Long.signum((long) lhs.getWidth() * lhs.getHeight() -
                (long) rhs.getWidth() * rhs.getHeight());
    }

}


}
在我看来,最重要的信息是:

06-23 19:37:20.381 18763-19545/  E/CameraDevice-JV-1: Lost output buffer reported for frame 107
06-23 19:37:20.381 18763-19545/  E/CameraDevice-JV-1: Lost output buffer reported for frame 107
06-23 19:37:23.391 18763-19555/  E/RequestThread-1: Timed out while waiting for request to complete.
06-23 19:37:23.391 18763-19555/  W/RequestHolder: Capture failed for request: 1
06-23 19:37:26.391 18763-19555/  E/RequestThread-1: Timed out while waiting for request to complete.

我不知道是什么导致了这个问题。当我按下录制按钮时,我的视频冻结了。知道这些设备有什么限制吗?什么是正确的相机设置?

您应该在录制时更新预览

@Override
                public void run() {
                    // UI
                    countDownTimer.start();
                    mIsRecordingVideo = true;

                    //Add this line
                    updatePreview();

                    // Start recording
                    mMediaRecorder.start();
                }

您应该在录制时更新预览

@Override
                public void run() {
                    // UI
                    countDownTimer.start();
                    mIsRecordingVideo = true;

                    //Add this line
                    updatePreview();

                    // Start recording
                    mMediaRecorder.start();
                }

是华为吗?…是华为吗?。。。