本文介绍了CamcorderProfile.videoCodec返回错误的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据文档,您可以使用CamcorderProfile来获取设备默认的视频编解码器格式,然后将其设置为MediaRecorder,如下所示:

According to the docs, you can use CamcorderProfile to get the devices default video codec format, then set it to MediaRecorder, like this:

CamcorderProfile mProfile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);

//

mMediaRecorder.setVideoEncoder(mProfile.videoCodec);

但是由于某种原因,它返回了错误的格式.

But for some reason it is returning the wrong format.

我正在使用 CameraView 库和 FullVideoRecorder 类,定义了以下内容:

I'm using the CameraView library and in the FullVideoRecorder class the following is defined:

switch (mResult.getVideoCodec()) {
    case H_263: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263); break;
    case H_264: mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); break;
    case DEVICE_DEFAULT: mMediaRecorder.setVideoEncoder(mProfile.videoCodec); break;
}

当我将视频编码器设置为H_263时,遇到问题的设备可以正常工作,但是由于某种原因,当我将其设置为默认值时,它会崩溃-在这种情况下,默认值表示CamcorderProfile应该选择设备默认的视频编解码器格式.

The device I'm experiencing the issue with works perfectly fine when I set the video encoder to H_263, but for some reason, when I set it to default it crashes - In this case default means that CamcorderProfile should select the devices default video codec format.

我的问题:

CamcorderProfile.videoCodec是否有任何原因会返回错误的值,并且该如何解决?

Is there any reason why CamcorderProfile.videoCodec would return the wrong value and how can this be resolved?

编辑-添加更多信息

我实现了以下内容,以确保CamcoderProfile是否返回错误的值:

I implemented the following to make sure if CamcoderProfile is returning the wrong value:

//In onCreate
CamcorderProfile camcorderProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH);

//getVideoCodec method below
String profileCodec = getVideoCodec(camcorderProfile.videoCodec);

//Log the result I get
Log.e("Video Codec =", profileCodec);


private String getVideoCodec(int videoCodec){
    switch(videoCodec){
        case MediaRecorder.VideoEncoder.H263:
            return "H263";
        case MediaRecorder.VideoEncoder.H264:
            return "H264";
        case MediaRecorder.VideoEncoder.MPEG_4_SP:
            return "MPEG_4_SP";
        case MediaRecorder.VideoEncoder.DEFAULT:
            return "DEFAULT";
        default:
            return "unknown";
    }
}

在我的日志中,我得到Video Codec = H264,但这是不正确的,它应该返回Video Codec = H263.

In my log I get Video Codec = H264, but this is incorrect, it should return Video Codec = H263.

如果我将以下内容传递给MediaRecorder,则可以正常运行:

If I pass the following to MediaRecorder, it works perfectly:

mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H263);

但是当我设置以下任何一项时,不是:

but not when I set any of the following:

mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);
mMediaRecorder.setVideoEncoder(mProfile.videoCodec);

推荐答案

问题似乎出在库中.让我解释一下.

It seems that the issue is with the library. Let me explain..

在查看 OpenCamera 的实现方式之后,我注意到他们首先检查是否camCoderProfile具有CamcorderProfile.QUALITY...,然后设置配置文件并沿配置文件的大小传递,如下所示:

After having a look at how OpenCamera implemented their camera, I noticed that they first check if camCoderProfile has CamcorderProfile.QUALITY... then setting the profile and passing along the size of the profile, as shown below:

private void initialiseVideoQuality() {
    int cameraId = camera_controller.getCameraId();
    List<Integer> profiles = new ArrayList<>();
    List<VideoQualityHandler.Dimension2D> dimensions = new ArrayList<>();

    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_HIGH) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH);
        profiles.add(CamcorderProfile.QUALITY_HIGH);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ) {
        if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_2160P) ) {
            CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_2160P);
            profiles.add(CamcorderProfile.QUALITY_2160P);
            dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
        }
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_1080P) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_1080P);
        profiles.add(CamcorderProfile.QUALITY_1080P);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_720P) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_720P);
        profiles.add(CamcorderProfile.QUALITY_720P);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_480P) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_480P);
        profiles.add(CamcorderProfile.QUALITY_480P);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_CIF) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_CIF);
        profiles.add(CamcorderProfile.QUALITY_CIF);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_QVGA) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_QVGA);
        profiles.add(CamcorderProfile.QUALITY_QVGA);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_QCIF) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_QCIF);
        profiles.add(CamcorderProfile.QUALITY_QCIF);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    if( CamcorderProfile.hasProfile(cameraId, CamcorderProfile.QUALITY_LOW) ) {
        CamcorderProfile profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_LOW);
        profiles.add(CamcorderProfile.QUALITY_LOW);
        dimensions.add(new VideoQualityHandler.Dimension2D(profile.videoFrameWidth, profile.videoFrameHeight));
    }
    this.video_quality_handler.initialiseVideoQualityFromProfiles(profiles, dimensions);
}

如果支持的配置文件宽度为1920,高度为1080,则看来OpenCamera只会将视频质量从default/0更改为水平-我认为这是因为摄像机的活动始终处于横向状态:

It looks like OpenCamera only changes the video quality from default/0, if the supported profile width is 1920 and hight is 1080 - I think it is because the camera activity is always in landscape:

if( video_quality_handler.getCurrentVideoQualityIndex() == -1 && video_quality_handler.getSupportedVideoQuality().size() > 0 ) {
video_quality_handler.setCurrentVideoQualityIndex(0); // start with highest quality

//If I log video_quality_handler.getSupportedVideoQuality() here, I get:
//[1, 5_r1440x1080, 5, 4_r960x720, 4_r800x450, 4, 7_r640x480, 7_r480x320, 7_r352x288, 7, 2]
//With 1 being QUALITY_HIGH
//https://developer.android.com/reference/android/media/CamcorderProfile.html#constants_2

for(int i=0;i<video_quality_handler.getSupportedVideoQuality().size();i++) {
    CamcorderProfile profile = getCamcorderProfile(video_quality_handler.getSupportedVideoQuality().get(i));
        if( profile.videoFrameWidth == 1920 && profile.videoFrameHeight == 1080 ) {
            video_quality_handler.setCurrentVideoQualityIndex(i);
            break;
        }
    }
}

private CamcorderProfile getCamcorderProfile(String quality) {
    if( camera_controller == null ) {
        //Camera is not opened
        return CamcorderProfile.get(0, CamcorderProfile.QUALITY_HIGH);
    }

    int cameraId = camera_controller.getCameraId();
    CamcorderProfile camcorder_profile = CamcorderProfile.get(cameraId, CamcorderProfile.QUALITY_HIGH); // default
        try {
            String profile_string = quality;
            int index = profile_string.indexOf('_');
            if( index != -1 ) {
                profile_string = quality.substring(0, index);
            }
            int profile = Integer.parseInt(profile_string);
            camcorder_profile = CamcorderProfile.get(cameraId, profile);
            if( index != -1 && index+1 < quality.length() ) {
                String override_string = quality.substring(index+1);
                    if( override_string.charAt(0) == 'r' && override_string.length() >= 4 ) {
                        index = override_string.indexOf('x');
                        if( index == -1 ) {
                            Log.d(TAG, "override_string invalid format, can't find x");
                        }
                        else {
                            String resolution_w_s = override_string.substring(1, index); // skip first 'r'
                            String resolution_h_s = override_string.substring(index+1);
                            // copy to local variable first, so that if we fail to parse height, we don't set the width either
                            int resolution_w = Integer.parseInt(resolution_w_s);
                            int resolution_h = Integer.parseInt(resolution_h_s);
                            camcorder_profile.videoFrameWidth = resolution_w;
                            camcorder_profile.videoFrameHeight = resolution_h;
                        }
                    }
                    else {
                        Log.d(TAG, "unknown override_string initial code, or otherwise invalid format");
                    }
                }
            }
            catch(NumberFormatException e) {
                e.printStackTrace();
            }
        return camcorder_profile;
    }
}

现在,我将使用与OpenCamera相同的实现.由于它是根据 GPLv3 许可的,因此我将项目更改为仅实现视频在此处录音并提供源代码.

For now, I will be using the same implementation OpenCamera used. Since it is licensed under GPLv3, I have change the project to only implement video recording and made the source code available here.

这篇关于CamcorderProfile.videoCodec返回错误的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-30 16:54