Android 12 mtk SytemUI 屏幕录制报错问题

文章讲述了在MTKAndroid12平台上进行屏幕录制时遇到的错误,主要问题是MediaRecorder提示尺寸不支持。作者通过分析源码,找到了获取设备支持的最大屏幕尺寸和帧率的方法,并提供了调整录制尺寸和帧率的解决方案。此外,还提及了一个在DisplayLayout.java中导致NullPointerException的问题,并给出了添加null判断的修复建议。
摘要由CSDN通过智能技术生成

最近在做mtk android 12 的项目时,遇到状态栏屏幕录制报错问题

屏幕的分辨率为1920x1200的,MediaRecorde提示尺寸不支持,看下源码

/**
     * Find the highest supported screen resolution and refresh rate for the given dimensions on
     * this device, up to actual size and given rate.
     * If possible this will return the same values as given, but values may be smaller on some
     * devices.
     *
     * @param screenWidth Actual pixel width of screen
     * @param screenHeight Actual pixel height of screen
     * @param refreshRate Desired refresh rate
     * @return array with supported width, height, and refresh rate
     */
    private int[] getSupportedSize(final int screenWidth, final int screenHeight, int refreshRate) {
        double maxScale = 0;

        MediaCodecList codecList = new MediaCodecList(MediaCodecList.REGULAR_CODECS);
        MediaCodecInfo.VideoCapabilities maxInfo = null;
        for (MediaCodecInfo codec : codecList.getCodecInfos()) {
            String videoType = MediaFormat.MIMETYPE_VIDEO_AVC;
            String[] types = codec.getSupportedTypes();
            for (String t : types) {
                if (!t.equalsIgnoreCase(videoType)) {
                    continue;
                }
                MediaCodecInfo.CodecCapabilities capabilities =
                        codec.getCapabilitiesForType(videoType);
                if (capabilities != null && capabilities.getVideoCapabilities() != null) {
                    MediaCodecInfo.VideoCapabilities vc = capabilities.getVideoCapabilities();

                    int width = vc.getSupportedWidths().getUpper();
                    int height = vc.getSupportedHeights().getUpper();

                    int screenWidthAligned = screenWidth;
                    if (screenWidthAligned % vc.getWidthAlignment() != 0) {
                        screenWidthAligned -= (screenWidthAligned % vc.getWidthAlignment());
                    }
                    int screenHeightAligned = screenHeight;
                    if (screenHeightAligned % vc.getHeightAlignment() != 0) {
                        screenHeightAligned -= (screenHeightAligned % vc.getHeightAlignment());
                    }

                    if (width >= screenWidthAligned && height >= screenHeightAligned
                            && vc.isSizeSupported(screenWidthAligned, screenHeightAligned)) {
                        // Desired size is supported, now get the rate
                        int maxRate = vc.getSupportedFrameRatesFor(screenWidthAligned,
                                screenHeightAligned).getUpper().intValue();

                        if (maxRate < refreshRate) {
                            refreshRate = maxRate;
                        }
                        Log.d(TAG, "Screen size supported at rate " + refreshRate);
                        return new int[]{screenWidthAligned, screenHeightAligned, refreshRate};
                    }

                    // Otherwise, continue searching
                    double scale = Math.min(((double) width / screenWidth),
                            ((double) height / screenHeight));
                    if (scale > maxScale) {
                        maxScale = Math.min(1, scale);
                        maxInfo = vc;
                    }
                }
            }
        }

        // Resize for max supported size
        int scaledWidth = (int) (screenWidth * maxScale);
        int scaledHeight = (int) (screenHeight * maxScale);
        if (scaledWidth % maxInfo.getWidthAlignment() != 0) {
            scaledWidth -= (scaledWidth % maxInfo.getWidthAlignment());
        }
        if (scaledHeight % maxInfo.getHeightAlignment() != 0) {
            scaledHeight -= (scaledHeight % maxInfo.getHeightAlignment());
        }

        // Find max supported rate for size
        int maxRate = maxInfo.getSupportedFrameRatesFor(scaledWidth, scaledHeight)
                .getUpper().intValue();
        if (maxRate < refreshRate) {
            refreshRate = maxRate;
        }

        Log.d(TAG, "Resized by " + maxScale + ": " + scaledWidth + ", " + scaledHeight
                + ", " + refreshRate);
        return new int[]{scaledWidth, scaledHeight, refreshRate};
    }

这就是SystemUI获取屏幕录制时支持的尺寸和帧率,录制成功需要尺寸和帧率都支持才可以录制成功.此时录制直接报错int maxRate = maxInfo.getSupportedFrameRatesFor(scaledWidth, scaledHeight).getUpper().intValue();,提示错误为尺寸不支持.所以我们这边只需要修改默认尺寸和帧率就可以了

private void prepare() throws IOException, RemoteException, RuntimeException {
        //Setup media projection
        IBinder b = ServiceManager.getService(MEDIA_PROJECTION_SERVICE);
        IMediaProjectionManager mediaService =
                IMediaProjectionManager.Stub.asInterface(b);
        IMediaProjection proj = null;
        proj = mediaService.createProjection(mUser, mContext.getPackageName(),
                    MediaProjectionManager.TYPE_SCREEN_CAPTURE, false);
        IBinder projection = proj.asBinder();
        mMediaProjection = new MediaProjection(mContext,
                IMediaProjection.Stub.asInterface(projection));

        File cacheDir = mContext.getCacheDir();
        cacheDir.mkdirs();
        mTempVideoFile = File.createTempFile("temp", ".mp4", cacheDir);

        // Set up media recorder
        mMediaRecorder = new MediaRecorder();

        // Set up audio source
        if (mAudioSource == MIC) {
            mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.DEFAULT);
        }
        mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);

        mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);


        // Set up video
        DisplayMetrics metrics = new DisplayMetrics();
        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        wm.getDefaultDisplay().getRealMetrics(metrics);
        int refreshRate = (int) wm.getDefaultDisplay().getRefreshRate();
        /*int[] dimens = getSupportedSize(metrics.widthPixels, metrics.heightPixels, refreshRate);
        int width = dimens[0];
        int height = dimens[1];
        refreshRate = dimens[2];*/
        
        //Modify start 
        //int[] dimens = getSupportedSize(metrics.widthPixels, metrics.heightPixels, refreshRate);
        final boolean isPortrait = mContext.getResources().getConfiguration().orientation
                == Configuration.ORIENTATION_PORTRAIT;
        int width;
        int height;
        Log.d(TAG, "[prepare] isPortrait " + isPortrait);
        if (isPortrait) {
            width = 1080;
            height = 1920;
        } else {
            width = 1920;
            height = 1080;
        }
        refreshRate = 30;
        //Modify end

        int vidBitRate = width * height * refreshRate / VIDEO_FRAME_RATE
                * VIDEO_FRAME_RATE_TO_RESOLUTION_RATIO;
        mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mMediaRecorder.setVideoEncodingProfileLevel(
                MediaCodecInfo.CodecProfileLevel.AVCProfileHigh,
                MediaCodecInfo.CodecProfileLevel.AVCLevel3);
        mMediaRecorder.setVideoSize(width, height);
        mMediaRecorder.setVideoFrameRate(refreshRate);
        mMediaRecorder.setVideoEncodingBitRate(vidBitRate);
        mMediaRecorder.setMaxDuration(MAX_DURATION_MS);
        mMediaRecorder.setMaxFileSize(MAX_FILESIZE_BYTES);

        // Set up audio
        if (mAudioSource == MIC) {
            mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.HE_AAC);
            mMediaRecorder.setAudioChannels(TOTAL_NUM_TRACKS);
            mMediaRecorder.setAudioEncodingBitRate(AUDIO_BIT_RATE);
            mMediaRecorder.setAudioSamplingRate(AUDIO_SAMPLE_RATE);
        }

        mMediaRecorder.setOutputFile(mTempVideoFile);
        mMediaRecorder.prepare();
        // Create surface
        mInputSurface = mMediaRecorder.getSurface();
        mVirtualDisplay = mMediaProjection.createVirtualDisplay(
                "Recording Display",
                width,
                height,
                metrics.densityDpi,
                DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                mInputSurface,
                null,
                null);

        mMediaRecorder.setOnInfoListener(mListener);
        if (mAudioSource == INTERNAL ||
                mAudioSource == MIC_AND_INTERNAL) {
            mTempAudioFile = File.createTempFile("temp", ".aac",
                    mContext.getCacheDir());
            mAudio = new ScreenInternalAudioRecorder(mTempAudioFile.getAbsolutePath(),
                    mMediaProjection, mAudioSource == MIC_AND_INTERNAL);
        }

    }

屏幕录制尺寸支持问题已解决,由于我这边还出现了一个frameworks层的DisplayLayout.java文件报了一个NullPointerException,还需要加一个null判断

 路径:frameworks/base/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java

    /** sets this DisplayLayout to a copy of another on. */
    public void set(DisplayLayout dl) {
        //Modify start 
        if(dl!=null){
           mUiMode = dl.mUiMode;
           mWidth = dl.mWidth;
           mHeight = dl.mHeight;
           mCutout = dl.mCutout;
           mRotation = dl.mRotation;
           mDensityDpi = dl.mDensityDpi;
           mHasNavigationBar = dl.mHasNavigationBar;
           mHasStatusBar = dl.mHasStatusBar;
           mNavBarFrameHeight = dl.mNavBarFrameHeight;
           mNonDecorInsets.set(dl.mNonDecorInsets);
           mStableInsets.set(dl.mStableInsets);        
        }
        //Modify end
    }

至此,屏幕录制报错问题解决

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值