软件开发教程 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试
游戏开发 网络协议 系统运维 HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程
C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
 
   -> 移动开发 -> Android8.0平台摄像头camera花屏问题 -> 正文阅读

[移动开发]Android8.0平台摄像头camera花屏问题

使用场景:在会议平台上经常使用摄像头会议视频,市场上摄像头也是各式各样,2K、4K的都很多,还有一些网络摄像头。

遇到问题:插上摄像头,软件打开摄像头,画面显示花屏或者黑屏。

问题分析:通过抓取log分析,怀疑是摄像头分辨率跟上层软件设置的分辨率不匹配,也可能是分辨率过大导致内存溢出。

代码修改:

文件路径:vendor/mstar/hardware/camera/HAL/CameraHardware.cpp? ? 不一样的平台路径存在差异,本人使用的是Mstar平台。

1、在该文件下有个tryCameraSupportedSize()函数,该函数可获取当前摄像头所支持的分辨率。


/**
  try camera supported size
 */
void CameraHardware::tryCameraSupportedSize() {
    const char *ResolutionSize[] = {"1920x1080", "1280x720", "640x480", "352x288", "384x216", "320x240", "176x144"};
    int count = 0;
    int ImageFormat;
    mCameraSupportedSize = new char[60];
    mVideoSupportedSize = new char[60];
    mVideoSupportedSize[0] = '\0';
    mHighQualityPreviewSizeForVideo = new char[10];
    for (int i = 0 ; i < sizeof(ResolutionSize)/sizeof(char *); i++) {
        char *end;
        int width = (int)strtol(ResolutionSize[i], &end, 10);
        int height = (int)strtol(end+1, &end, 10);
        //if (width == WIDTH_1080P && (!checkVideoSupported1080p() || !mJpegDecoder.is1080pSupport())) {
        if (width == WIDTH_1080P && (!mJpegDecoder.is1080pSupport())) {
            i++;
            width = (int)strtol(ResolutionSize[i], &end, 10);
            height = (int)strtol(end+1, &end, 10);
        }

#if YUV_DATA_ONLY
        ImageFormat = V4L2_PIX_FMT_YUYV;
#else
        if (width >= WIDTH_720P) {
            ImageFormat = V4L2_PIX_FMT_MJPEG;
        } else {
            ImageFormat = V4L2_PIX_FMT_YUYV;
        }
#endif
        if (!(mCamera->tryParameters(width, height, ImageFormat))) {
            if (count == 0) {
                mWidth = width;
                mHeight = height;
                if (width >= WIDTH_720P) {
                    m720pSupported = true;
                }
                sprintf(mHighQualityPreviewSizeForVideo, "%s", ResolutionSize[i]);
                sprintf(mCameraSupportedSize, "%s", ResolutionSize[i]);
				maxIndex = i; //add by jude for 用于获取最大分辨率

            } else {
                sprintf(mCameraSupportedSize, "%s,%s", mCameraSupportedSize, ResolutionSize[i]);
            }

            if (mVideoSupportedSize[0] == '\0') {
                sprintf(mVideoSupportedSize, "%s", ResolutionSize[i]);
            } else {
                sprintf(mVideoSupportedSize, "%s,%s", mVideoSupportedSize, ResolutionSize[i]);
            }

            count++;
        } else {
            // always add video size 352x288 and 176x144 for CTS
            if ((width == 352 && height == 288) || (width == 176 && height == 144)) {
                if (mVideoSupportedSize[0] == '\0') {
                    sprintf(mVideoSupportedSize, "%s", ResolutionSize[i]);
                } else {
                    sprintf(mVideoSupportedSize, "%s,%s", mVideoSupportedSize, ResolutionSize[i]);
                }
            }
        }
    }
    ALOGI("---Camera Supported Size list: %s", mCameraSupportedSize);

	//获取最大分辨率
	if(maxIndex == 0){
		maxWidth = 1920;
		maxHeight = 1080;
	}else if(maxIndex == 1){
		maxWidth = 1280;
		maxHeight = 720;
	}else if(maxIndex == 2){
		maxWidth = 640;
		maxHeight = 480;
	}else{
		maxWidth = 1280;
		maxHeight = 720;
	}
	tempWidth = maxWidth;
	tempHeight = maxHeight;
	ALOGI("---Camera maxWidth==: %d", maxWidth);
	ALOGI("---Camera maxHeigh==: %d", maxHeight);
}

2、获取到最大分辨率后,在设置摄像头参数。CameraHardware.cpp文件中有个setParameters()函数,该函数直接设置camera各项参数。首先获取上层apk设置的预览窗大小getPreviewSize();其次通过之前获取的最大分辨率设置camera的mImageFormat;然后若上层设置的预览窗大小在camera的支持分辨率下,则设置预览窗大小为上层设置的;若不在camera支持范围,则强制设置为camera支持的分辨率。

/**
   @brief Set the camera parameters.

   @param[in] params Camera parameters to configure the camera
   @return NO_ERROR
   @todo Define error codes

 */
int CameraHardware::setParameters(const char* parameters) {
    unsigned int i;
    int width, height;
    int min_fps, max_fps;
    Vector<Size> sizes;
    CameraParameters params;
    String8 str_params(parameters);
    params.unflatten(str_params);
    status_t ret = NO_ERROR;
    bool tempPreviewEnabled = mPreviewEnabled;
    mPreviewEnabled = false;
    Mutex::Autolock lock(mLock);
    //Mutex::Autolock lock(mTakePictureLock);

    params.getSupportedPreviewSizes(sizes);
    params.getPreviewSize(&width, &height);

    params.getPreviewFpsRange(&min_fps ,&max_fps);
    if (min_fps < 0 || max_fps < 0)
        return BAD_VALUE;
    else if ((max_fps - min_fps) < 0)
        return BAD_VALUE;

    if (width < 0 || height < 0)
        return BAD_VALUE;

    if (strcmp("invalid",params.get(CameraParameters::KEY_FOCUS_MODE)) == 0)
        return BAD_VALUE;

    if (strcmp("invalid",params.get(CameraParameters::KEY_FLASH_MODE)) == 0)
        return BAD_VALUE;


    mParameters = params;

    //Add some camera parameter logs for debug
    //ALOGD("%s - CameraParameters::KEY_FLASH_MODE is %s", __FUNCTION__, mParameters.get(CameraParameters::KEY_FLASH_MODE));
    //ALOGD("%s  - CameraParameters::KEY_AUTO_EXPOSURE_LOCK is %s", __FUNCTION__, mParameters.get(CameraParameters::KEY_AUTO_EXPOSURE_LOCK));

    width = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH);
    height = mParameters.getInt(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT);

    mThumbnailWidth = width;
    mThumbnailHeight = height;

    mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_WIDTH, mThumbnailWidth);
    mParameters.set(CameraParameters::KEY_JPEG_THUMBNAIL_HEIGHT, mThumbnailHeight);
    
    //获取预览窗的分辨率
    mParameters.getSupportedPreviewSizes(sizes);
    mParameters.getPreviewSize(&width, &height);
    
    //ALOGI("===getPreviewSize to %d, %d",width,height);
    //通过最大分辨率设置camera的图像格式
    if ((maxWidth >= WIDTH_720P) && (maxHeight >= HEIGHT_720P)) {
        //ALOGE("===Is 720P , change V4L2_PIX_FMT_MJPEG ");
        mImageFormat = V4L2_PIX_FMT_MJPEG;
    } else {
        mImageFormat = V4L2_PIX_FMT_YUYV;
    }

	if(width <= 640 && height <= 480){
		tempWidth = 640;
		tempHeight = 480;
	}
	//ALOGI("===MaxSize to %d, %d",maxWidth,maxHeight);
	width = tempWidth;
	height = tempHeight;

    for (i = 0; i < sizes.size(); i++)
        if (width == sizes[i].width && height == sizes[i].height)
            break;

    if (i == sizes.size()) {
        params.getPreferredPreviewSizeForVideo(&width, &height);
        if ((width <= 0) || (height <= 0))
            mParameters.getPreviewSize(&width, &height);
        ALOGI("Change preview size to %dx%d", width, height);
    }

    //Modify by jude for some camera can't work, 20200912
    mParameters.setPreviewSize(width, height);
    ALOGI("===setPreviewSize to %d, %d",width,height);
	//end jude

    if (mWidth == width && mHeight == height) {
        mPreviewEnabled = tempPreviewEnabled;
        return NO_ERROR;
    }

    //If change the camera preview size, mPreviewLock should be lock
    Mutex::Autolock previewlock(mPreviewLock);
    mPreviewEnabled = tempPreviewEnabled;
    mWidth = width;
    mHeight = height;

    //Some Cameras cannot open/close so quickly
    usleep(1000 * 100);
    mCamera->StopStreaming();
    mCamera->Uninit();
    mCamera->Close();

    if (mPreviewMemory)
        mPreviewMemory->release(mPreviewMemory);

    ret = mCamera->Open(mCameraDev);
    if (ret == -1) {
        ALOGE("Camera device open failed.");
    }

    ret = mCamera->setParameters(mWidth, mHeight, mImageFormat);
    if (ret) {
        ALOGE("Camera setParameters failed: %s", strerror(errno));
    }

    ret = mCamera->Init();
    if (ret) {
        ALOGE("Camera Init failed: %s", strerror(errno));
    }

    ret = mCamera->StartStreaming();
    if (ret) {
        ALOGE("Camera StartStreaming failed: %s", strerror(errno));
    }

    if (strcmp(mParameters.getPreviewFormat(), CameraParameters::PIXEL_FORMAT_YUV420SP) == 0 ) {
        // YUV420SP
        mPreviewFrameSize = mWidth * mHeight * 3 / 2;
    } else if (strcmp(mParameters.getPreviewFormat(), CameraParameters::PIXEL_FORMAT_YUV420P) == 0) {
        mPreviewFrameSize = calculateYUV420PSize(mWidth, mHeight);
    } else {
        // YUV422
        mPreviewFrameSize = mWidth * mHeight * 2;
    }

    mPreviewMemory = mRequestMemory(-1, mPreviewFrameSize, 1, mCallbackCookie);
	
    ALOGI("jude===mPreviewFrameSize to %d", mPreviewFrameSize); 
	ALOGI("jude===mPreviewMemory alloc %x", (unsigned int)mPreviewMemory);

    mBounds.left = 0;
    mBounds.top = 0;
    mBounds.right = mWidth;
    mBounds.bottom = mHeight;

    return NO_ERROR;
}

  移动开发 最新文章
Android开发中recycleview子项宽度无法撑满
2021-07-24
【Kotlin】kotlin中的空指针检查
多种网络请求方式 ,这么骚气的操作确定不来
营销运作百科:什么是小程序,小程序的发展
Android - 禁用权限后,进程被杀?
Flutter WebView使用以及分析
Android 播放帧动画2
[android驱动] Ftrace使用记录
Unity(C#)和Android(java)通过反射相互调用
上一篇文章      下一篇文章      查看所有文章
加:2021-07-17 12:03:47  更:2021-07-17 12:05:49 
 
360图书馆 购物 三丰科技 阅读网 日历 万年历 2021年7日历 -2021/7/27 3:12:35-
图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  软件开发教程