【问题标题】:How to solve artifact issue with front camera video recording on some Android devices?如何解决某些 Android 设备上前置摄像头视频录制的伪影问题?
【发布时间】:2014-03-13 20:39:40
【问题描述】:

我正在尝试以编程方式从 Android 设备的前置摄像头录制视频。虽然我拥有的大多数测试设备(包括 Nexus 4、Nexus 7 和三星 Galaxy S4)都能正确录制视频,但有些则不能。

例如,下面是三星 Galaxy S3 录制的一段视频截图:

有奇怪的伪影和颜色,视频似乎没有居中(它指向一个人的脸,你可以看到在镜头中几乎看不到)。

这是我的代码:

//
// starting code
//

CAMERA = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT);
Camera.Parameters cameraParameters = CAMERA.getParameters();
if (cameraParameters.isZoomSupported()) {
    cameraParameters.setZoom(0);
}
CAMERA.setParameters(cameraParameters);
CAMERA.setDisplayOrientation(90);

CAMERA.setPreviewDisplay(CAMERA_SURFACE_VIEW.getHolder());
CAMERA.startPreview();
CAMERA.unlock();

CAMERA_MEDIA_RECORDER = new MediaRecorder();
CAMERA_MEDIA_RECORDER.setCamera(CAMERA);
try {
    CAMERA_MEDIA_RECORDER.setOrientationHint(270);
} catch (Exception e) {
    // this is to fix "setParameter failed" b/c of unsupported orientation hint
    CAMERA_MEDIA_RECORDER.setOrientationHint(90);
}
CAMERA_MEDIA_RECORDER.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);
CAMERA_MEDIA_RECORDER.setVideoSource(MediaRecorder.VideoSource.CAMERA);

ArrayList<Integer> profileIds = new ArrayList<Integer>();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    profileIds.add(CamcorderProfile.QUALITY_480P);
    profileIds.add(CamcorderProfile.QUALITY_720P);
}

profileIds.add(CamcorderProfile.QUALITY_HIGH);
profileIds.add(CamcorderProfile.QUALITY_LOW);

CamcorderProfile camcorderProfile = null;

for (int profileId : profileIds) {
    try {
        camcorderProfile = CamcorderProfile.get(Camera.CameraInfo.CAMERA_FACING_FRONT, profileId);
        break; // found our most desired profile, done
    } catch (IllegalArgumentException e) {
        // profile not found on device... It's okay, the next one might exist.
        continue;
    } catch (RuntimeException e) {
        continue;
    }
}

if (camcorderProfile == null) {
    return false;
}

CAMERA_MEDIA_RECORDER.setProfile(camcorderProfile);
CAMERA_MEDIA_RECORDER.setAudioEncodingBitRate(96000);

int audioSamplingRate = 44100;

for (int rate : new int[] {44100, 32000, 22050, 16000, 11025, 8000}) {
    if (AudioRecord.getMinBufferSize(rate, AudioFormat.CHANNEL_IN_DEFAULT, AudioFormat.ENCODING_PCM_16BIT) > 0) {
        audioSamplingRate = rate;
        break;
    }
}

CAMERA_MEDIA_RECORDER.setAudioSamplingRate(audioSamplingRate);
CAMERA_MEDIA_RECORDER.setVideoEncodingBitRate(700000);

String extension = ".3gpp";

if (camcorderProfile.fileFormat == MediaRecorder.OutputFormat.MPEG_4) {
    extension = ".mp4";
}

File file = new File(Internal.getStoragePath(Internal.CURRENT_ACTIVITY) + "/webcam" + extension);
file.createNewFile();

CAMERA_MEDIA_RECORDER.setOutputFile(file.toString());
CAMERA_MEDIA_RECORDER.setPreviewDisplay(CAMERA_SURFACE_VIEW.getHolder().getSurface());

CAMERA_MEDIA_RECORDER.prepare();
CAMERA_MEDIA_RECORDER.start();

//
// stopping code
//

try {
    CAMERA_MEDIA_RECORDER.stop();
} catch (IllegalStateException e) {
    // do nothing
} catch (RuntimeException e) {
    // do nothing
}

CAMERA_MEDIA_RECORDER.reset();
CAMERA_MEDIA_RECORDER.release();

CAMERA.lock();
CAMERA.stopPreview();
CAMERA.release();

CAMERA_MEDIA_RECORDER = null;
CAMERA = null;
CAMERA_SURFACE_VIEW = null;

编辑:我应该指出,surfaceView 是 1 x 1 像素,并且超出了屏幕的范围。我不想显示预览。

如何确保所有带有前置摄像头的设备都能正常录制视频?

【问题讨论】:

    标签: android android-camera android-mediarecorder


    【解决方案1】:

    “已接受”的答案只是一种解决方法,并不能解决问题,因为当您释放预览并开始录制时,缩放或纵横比可能会发生变化,因为 mediarecorder 会将预览表面调整到实际需要的状态,因此当您击中记录时,镜头的取景会发生变化,这是不可取的。正确的做法是将预览大小设置为与录制大小的纵横比一致,以便 mediarecorder 获得它期望的表面。

    检查Android相机应用程序,它不会停止预览然后开始录制(您可以通过保持闪光灯打开来检查这一点,如果您开始录制闪光灯不会关闭然后再次打开,如果您在录制之前释放表面 - 您可以在自己的应用程序中进行测试)。

    最好的办法是看看 Google 是如何使用内置的 Android 相机应用做到这一点的。查看他们的 util.java 类中的 getOptimalPreviewSize() 方法。

    https://android.googlesource.com/platform/packages/apps/Camera.git/+/master/src/com/android/camera/Util.java

    【讨论】:

    • 有什么更好的选择?有什么方法可以通过与 MediaRecorder 不同分辨率的预览来正确执行此操作?
    • 抱歉,稍作修正。找到具有相似纵横比的预览尺寸,不一定是完全相同的分辨率,还要考虑屏幕纵横比。 (在某些设备上,分辨率必须不同)。然后,您不必在录制之前停止相机预览作为解决方法,因为预览表面与录制器需要的一致。研究 Android Camera App 源代码,特别是 Util.java 中的 getOptimalPreviewSize 方法。这将解决它:android.googlesource.com/platform/packages/apps/Camera.git/+/…
    【解决方案2】:

    我终于能够拿到三星 Galaxy S3 设备并运行一些测试。该问题是由以下几行引起的:

    CAMERA.setPreviewDisplay(CAMERA_SURFACE_VIEW.getHolder());
    CAMERA.startPreview();
    

    我在 StackOverflow 上找到的以下答案引导我找到了解决方案:https://stackoverflow.com/a/14319270/379245

    如果SurfaceView 预览在CameraMediaRecorder 之间共享,它显然会导致我遇到的问题。从Camera 对象中删除预览显示的设置最终解决了这个问题。

    【讨论】:

    • 这不是我的问题的原因。只有当我使用前置摄像头并设置与视频大小不同的预览大小时,我的 Galaxy Note 2 才会面临同样的问题。所以我的问题是使用前置摄像头并设置与视频大小不同的预览大小时出现绿色粉红色伪影。你很幸运你以这种方式解决了它:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2021-06-03
    • 2023-01-27
    相关资源
    最近更新 更多