| /* |
| * Copyright (c) 2019, The Linux Foundation. All rights reserved. |
| |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials provided |
| * with the distribution. |
| * * Neither the name of The Linux Foundation nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include <dlfcn.h> |
| #include <log/log.h> |
| #include <mutex> |
| |
| #include "gr_camera_info.h" |
| #include "gralloc_priv.h" |
| |
| using std::lock_guard; |
| using std::mutex; |
| |
| namespace gralloc { |
| |
| CameraInfo *CameraInfo::s_instance = nullptr; |
| |
| CameraInfo *CameraInfo::GetInstance() { |
| static mutex s_lock; |
| lock_guard<mutex> obj(s_lock); |
| if (!s_instance) { |
| s_instance = new CameraInfo(); |
| } |
| |
| return s_instance; |
| } |
| |
| CameraInfo::CameraInfo() { |
| libcamera_utils_ = ::dlopen("libcamxexternalformatutils.so", RTLD_NOW); |
| if (libcamera_utils_) { |
| *reinterpret_cast<void **>(&LINK_camera_get_stride_in_bytes) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetStrideInBytes"); |
| *reinterpret_cast<void **>(&LINK_camera_get_stride_in_pixels) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetStrideInPixels"); |
| *reinterpret_cast<void **>(&LINK_camera_get_scanline) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetScanline"); |
| *reinterpret_cast<void **>(&LINK_camera_get_plane_size) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPlaneSize"); |
| *reinterpret_cast<void **>(&LINK_camera_get_buffer_size) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetBufferSize"); |
| *reinterpret_cast<void **>(&LINK_camera_get_ubwc_info) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetUBWCInfo"); |
| *reinterpret_cast<void **>(&LINK_camera_get_plane_alignment) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPlaneAlignment"); |
| *reinterpret_cast<void **>(&LINK_camera_get_plane_offset) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPlaneOffset"); |
| *reinterpret_cast<void **>(&LINK_camera_is_per_plane_fd_needed) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_IsPerPlaneFdNeeded"); |
| *reinterpret_cast<void **>(&LINK_camera_get_bpp) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetBpp"); |
| *reinterpret_cast<void **>(&LINK_camera_get_per_plane_bpp) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPerPlaneBpp"); |
| *reinterpret_cast<void **>(&LINK_camera_get_subsampling_factor) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetSubsamplingFactor"); |
| *reinterpret_cast<void **>(&LINK_camera_get_plane_count) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPlaneCount"); |
| *reinterpret_cast<void **>(&LINK_camera_get_plane_types) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPlaneTypes"); |
| *reinterpret_cast<void **>(&LINK_camera_get_pixel_increment) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPixelIncrement"); |
| *reinterpret_cast<void **>(&LINK_camera_get_plane_start_address_alignment) = |
| ::dlsym(libcamera_utils_, "CamxFormatUtil_GetPlaneStartAddressAlignment"); |
| } else { |
| ALOGE("%s: Failed to load libcamxexternalformatutils.so - %s", __FUNCTION__, strerror(errno)); |
| } |
| } |
| |
| CameraInfo::~CameraInfo() { |
| if (libcamera_utils_) { |
| ::dlclose(libcamera_utils_); |
| } |
| } |
| |
| CamxPixelFormat CameraInfo::GetCameraPixelFormat(int hal_format) { |
| CamxPixelFormat format = (CamxPixelFormat)0; |
| switch (hal_format) { |
| case HAL_PIXEL_FORMAT_NV21_ZSL: |
| format = CAMERA_PIXEL_FORMAT_NV21_ZSL; |
| break; |
| case HAL_PIXEL_FORMAT_NV12_LINEAR_FLEX: |
| format = CAMERA_PIXEL_FORMAT_YUV_FLEX; |
| break; |
| case HAL_PIXEL_FORMAT_NV12_UBWC_FLEX: |
| format = CAMERA_PIXEL_FORMAT_UBWC_FLEX; |
| break; |
| case HAL_PIXEL_FORMAT_MULTIPLANAR_FLEX: |
| format = CAMERA_PIXEL_FORMAT_MULTIPLANAR_FLEX; |
| break; |
| case HAL_PIXEL_FORMAT_RAW_OPAQUE: |
| format = CAMERA_PIXEL_FORMAT_RAW_OPAQUE; |
| break; |
| default: |
| ALOGE("%s: No map for format: 0x%x", __FUNCTION__, hal_format); |
| break; |
| } |
| |
| return format; |
| } |
| |
| int CameraInfo::GetBufferSize(int format, int width, int height, unsigned int *size) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_buffer_size) { |
| result = LINK_camera_get_buffer_size(GetCameraPixelFormat(format), width, height, size); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the buffer size. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetBufferSize. Error code : %d", __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetStrideInBytes(int format, int plane_type, int width, int *stride_bytes) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_stride_in_bytes) { |
| result = LINK_camera_get_stride_in_bytes(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), width, stride_bytes); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the stride in bytes. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetStrideInBytes. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetStrideInPixels(int format, int plane_type, int width, float *stride_pixel) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_stride_in_pixels) { |
| result = LINK_camera_get_stride_in_pixels(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), width, stride_pixel); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the stride in pixels. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetStrideInPixels. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPixelIncrement(int format, int plane_type, int *pixel_increment) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_pixel_increment) { |
| result = LINK_camera_get_pixel_increment(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), pixel_increment); |
| if (result != 0) { |
| ALOGE("%s: Failed to get pixel increment. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPixelIncrement. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPlaneOffset(int format, int plane_type, int *offset) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_plane_offset) { |
| result = LINK_camera_get_plane_offset(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), offset); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the plane offset. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPlaneOffset. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetSubsamplingFactor(int format, int plane_type, bool isHorizontal, |
| int *subsampling_factor) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_subsampling_factor) { |
| result = LINK_camera_get_subsampling_factor(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), isHorizontal, |
| subsampling_factor); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the sub-sampling factor. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetSubsamplingFactor. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPlaneTypes(int format, PlaneComponent *plane_component_array, int *plane_count) { |
| CamxPlaneType plane_types_array[8] = {}; |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_plane_types) { |
| result = |
| LINK_camera_get_plane_types(GetCameraPixelFormat(format), plane_types_array, plane_count); |
| if (result == 0) { |
| for (int plane = 0; plane < *plane_count; plane++) { |
| plane_component_array[plane] = GetPlaneComponent(plane_types_array[plane]); |
| } |
| } else { |
| ALOGE("%s: Failed to get the plane types. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPlaneTypes. Error code : %d", __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetScanline(int format, int plane_type, int height, int *scanlines) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_scanline) { |
| result = LINK_camera_get_scanline(GetCameraPixelFormat(format), GetCamxPlaneType(plane_type), |
| height, scanlines); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the scanlines. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetScanline. Error code : %d", __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPlaneSize(int format, int plane_type, int width, int height, |
| unsigned int *size) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_plane_size) { |
| result = LINK_camera_get_plane_size(GetCameraPixelFormat(format), GetCamxPlaneType(plane_type), |
| width, height, size); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the plane size. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPlaneSize. Error code : %d", __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetCameraFormatPlaneInfo(int format, int width, int height, int *plane_count, |
| PlaneLayoutInfo *plane_info) { |
| int h_subsampling = 0; |
| int v_subsampling = 0; |
| int offset = 0; |
| int pixel_increment = 0; |
| float stride_pixel = 0; |
| int stride_bytes = 0; |
| int scanlines = 0; |
| unsigned int plane_size = 0; |
| PlaneComponent plane_type[8] = {}; |
| int result; |
| result = GetPlaneTypes(format, plane_type, plane_count); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the plane types. Error code : %d", __FUNCTION__, result); |
| return result; |
| } |
| |
| for (int i = 0; i < *plane_count; i++) { |
| plane_info[i].component = plane_type[i]; |
| result = GetSubsamplingFactor(format, plane_type[i], true, &h_subsampling); |
| if (result != 0) { |
| ALOGE("%s: Failed to get horizontal subsampling factor. plane_type = %d, Error code : %d", |
| __FUNCTION__, plane_type[i], result); |
| break; |
| } |
| plane_info[i].h_subsampling = (uint32_t)h_subsampling; |
| |
| result = GetSubsamplingFactor(format, plane_type[i], false, &v_subsampling); |
| if (result != 0) { |
| ALOGE("%s: Failed to get vertical subsampling factor. plane_type = %d, Error code : %d", |
| __FUNCTION__, plane_type[i], result); |
| break; |
| } |
| plane_info[i].v_subsampling = (uint32_t)v_subsampling; |
| |
| result = GetPlaneOffset(format, plane_type[i], &offset); |
| if (result != 0) { |
| ALOGE("%s: Failed to get plane offset. plane_type = %d, Error code : %d", __FUNCTION__, |
| plane_type[i], result); |
| break; |
| } |
| plane_info[i].offset = (uint32_t)offset; |
| |
| result = GetPixelIncrement(format, plane_type[i], &pixel_increment); |
| if (result != 0) { |
| ALOGE("%s: Failed to get pixel increment. plane_type = %d, Error code : %d", __FUNCTION__, |
| plane_type[i], result); |
| break; |
| } |
| plane_info[i].step = (int32_t)pixel_increment; |
| |
| result = GetStrideInPixels(format, plane_type[i], width, &stride_pixel); |
| if (result != 0) { |
| ALOGE("%s: Failed to get stride in pixel. plane_type = %d, Error code : %d", __FUNCTION__, |
| plane_type[i], result); |
| break; |
| } |
| plane_info[i].stride = (int32_t)stride_pixel; |
| |
| result = GetStrideInBytes(format, plane_type[i], width, &stride_bytes); |
| if (result != 0) { |
| ALOGE("%s: Failed to get stride in bytes. plane_type = %d, Error code : %d", __FUNCTION__, |
| plane_type[i], result); |
| break; |
| } |
| plane_info[i].stride_bytes = (int32_t)stride_bytes; |
| |
| result = GetScanline(format, plane_type[i], height, &scanlines); |
| if (result != 0) { |
| ALOGE("%s: Failed to get scanlines. plane_type = %d, Error code : %d", __FUNCTION__, |
| plane_type[i], result); |
| break; |
| } |
| plane_info[i].scanlines = (int32_t)scanlines; |
| |
| result = GetPlaneSize(format, plane_type[i], width, height, &plane_size); |
| if (result != 0) { |
| ALOGE("%s: Failed to get plane size. plane_type = %d, Error code : %d", __FUNCTION__, |
| plane_type[i], result); |
| break; |
| } |
| plane_info[i].size = (uint32_t)plane_size; |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetUBWCInfo(int format, bool *is_supported, bool *is_pi, int *version) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_ubwc_info) { |
| result = LINK_camera_get_ubwc_info(GetCameraPixelFormat(format), is_supported, is_pi, version); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the UBWC info. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetUBWCInfo. Error code : %d", __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPlaneAlignment(int format, int plane_type, unsigned int *alignment) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_plane_alignment) { |
| result = LINK_camera_get_plane_alignment(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), alignment); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the plane alignment. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPlaneAlignment. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::IsPerPlaneFdNeeded(int format, bool *is_per_plane_fd_needed) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_is_per_plane_fd_needed) { |
| result = |
| LINK_camera_is_per_plane_fd_needed(GetCameraPixelFormat(format), is_per_plane_fd_needed); |
| if (result != 0) { |
| ALOGE("%s: Failed to get per_plane_fd flag. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_IsPerPlaneFdNeeded. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetBpp(int format, int *bpp) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_bpp) { |
| result = LINK_camera_get_bpp(GetCameraPixelFormat(format), bpp); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the bpp. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetBpp. Error code : %d", __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPerPlaneBpp(int format, int plane_type, int *bpp) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_per_plane_bpp) { |
| result = LINK_camera_get_per_plane_bpp(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), bpp); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the per plane bpp. Error code: %d", __FUNCTION__, result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPerPlaneBpp. Error code : %d", __FUNCTION__, |
| result); |
| } |
| |
| return result; |
| } |
| |
| int CameraInfo::GetPlaneStartAddressAlignment(int format, int plane_type, int *alignment) { |
| CamxFormatResult result = (CamxFormatResult)-1; |
| if (LINK_camera_get_plane_start_address_alignment) { |
| result = LINK_camera_get_plane_start_address_alignment(GetCameraPixelFormat(format), |
| GetCamxPlaneType(plane_type), alignment); |
| if (result != 0) { |
| ALOGE("%s: Failed to get the plane star address alignment. Error code: %d", __FUNCTION__, |
| result); |
| } |
| } else { |
| ALOGW("%s: Failed to link CamxFormatUtil_GetPlaneStartAddressAlignment. Error code : %d", |
| __FUNCTION__, result); |
| } |
| |
| return result; |
| } |
| |
| PlaneComponent CameraInfo::GetPlaneComponent(CamxPlaneType plane_type) { |
| PlaneComponent plane_component = (PlaneComponent)0; |
| switch (plane_type) { |
| case CAMERA_PLANE_TYPE_RAW: |
| plane_component = (PlaneComponent)PLANE_COMPONENT_RAW; |
| break; |
| case CAMERA_PLANE_TYPE_Y: |
| plane_component = (PlaneComponent)PLANE_COMPONENT_Y; |
| break; |
| case CAMERA_PLANE_TYPE_UV: |
| plane_component = (PlaneComponent)(PLANE_COMPONENT_Cb | PLANE_COMPONENT_Cr); |
| break; |
| case CAMERA_PLANE_TYPE_U: |
| plane_component = (PlaneComponent)PLANE_COMPONENT_Cb; |
| break; |
| case CAMERA_PLANE_TYPE_V: |
| plane_component = (PlaneComponent)PLANE_COMPONENT_Cr; |
| break; |
| case CAMERA_PLANE_TYPE_META_Y: |
| plane_component = (PlaneComponent)(PLANE_COMPONENT_META | PLANE_COMPONENT_Y); |
| break; |
| case CAMERA_PLANE_TYPE_META_VU: |
| plane_component = |
| (PlaneComponent)(PLANE_COMPONENT_META | PLANE_COMPONENT_Cb | PLANE_COMPONENT_Cr); |
| break; |
| default: |
| ALOGE("%s: No PlaneComponent mapping for plane_type: %d", __FUNCTION__, plane_type); |
| break; |
| } |
| |
| return plane_component; |
| } |
| |
| CamxPlaneType CameraInfo::GetCamxPlaneType(int plane_type) { |
| CamxPlaneType camx_plane_type = (CamxPlaneType)0; |
| switch (plane_type) { |
| case PLANE_COMPONENT_RAW: |
| camx_plane_type = CAMERA_PLANE_TYPE_RAW; |
| break; |
| case PLANE_COMPONENT_Y: |
| camx_plane_type = CAMERA_PLANE_TYPE_Y; |
| break; |
| case (PLANE_COMPONENT_Cb | PLANE_COMPONENT_Cr): |
| camx_plane_type = CAMERA_PLANE_TYPE_UV; |
| break; |
| case PLANE_COMPONENT_Cb: |
| camx_plane_type = CAMERA_PLANE_TYPE_U; |
| break; |
| case PLANE_COMPONENT_Cr: |
| camx_plane_type = CAMERA_PLANE_TYPE_V; |
| break; |
| case (PLANE_COMPONENT_META | PLANE_COMPONENT_Y): |
| camx_plane_type = CAMERA_PLANE_TYPE_META_Y; |
| break; |
| case (PLANE_COMPONENT_META | PLANE_COMPONENT_Cr | PLANE_COMPONENT_Cb): |
| camx_plane_type = CAMERA_PLANE_TYPE_META_VU; |
| break; |
| default: |
| ALOGE("%s: No CamxPlane for plane_type: %d", __FUNCTION__, plane_type); |
| break; |
| } |
| |
| return camx_plane_type; |
| } |
| |
| } // namespace gralloc |