自 2025 年 3 月 27 日起,我们建议您使用 android-latest-release
而非 aosp-main
构建 AOSP 并为其做出贡献。如需了解详情,请参阅 AOSP 的变更。
输出流、剪裁和缩放
使用集合让一切井井有条
根据您的偏好保存内容并对其进行分类。
输出流
相机子系统针对所有分辨率和输出格式都仅在基于 ANativeWindow 的管道上运行。您可以一次配置多个流,以便将单个帧发送至多个目标,例如:GPU、视频编码器、RenderScript,或应用可见的缓冲区(RAW Bayer 缓冲区、经处理的 YUV 缓冲区或经 JPEG 编码的缓冲区)。
出于优化的目的,这些输出流必须提前配置,而且只有有限的输出流可同时存在。这样一来,就可以预先分配内存缓冲区并配置相机硬件,以便在列出多个或者不同输出管道的情况下提交请求时,不会出现请求延迟执行的情况。
如需详细了解取决于受支持的硬件级别的保证流输出组合,请参阅 createCaptureSession()
。
剪裁
完整像素阵列的剪裁(用于数字变焦和需要更小 FOV 的其他使用情况)通过 ANDROID_SCALER_CROP_REGION 设置进行传递。这个设置可按需更改,这种方式对于实现平滑的数字变焦至关重要。
该区域被定义为矩形(x 和 y 分别表示宽和高),其中 (x,y) 表示矩形的左上角。该矩形在传感器有源像素阵列的坐标系中进行定义,其中 (0,0) 对应有源像素阵列的左上角像素。因此,宽度和高度不能大于 ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY 静态信息字段中所报告的尺寸。允许的最小宽度和高度由 HAL 通过 ANDROID_SCALER_MAX_DIGITAL_ZOOM 静态信息字段进行报告,该字段描述了所支持的缩放因子的最大值。因此,最小剪裁区域的宽度和高度为:
{width, height} =
{ floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[0] /
ANDROID_SCALER_MAX_DIGITAL_ZOOM),
floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[1] /
ANDROID_SCALER_MAX_DIGITAL_ZOOM) }
如果剪裁区域需要满足特定需求(例如:要求起始位置坐标为偶数,并且其宽度/高度需均为偶数),则 HAL 必须进行必要的舍入运算,并写出输出结果元数据中所用的最终剪裁区域。同样,HAL 要实现视频防抖功能,则必须调整结果剪裁区域,以描述在应用视频防抖功能后输出结果中实际包含的区域。一般情况下,使用相机的应用必须能够根据剪裁区域、图像传感器的尺寸和镜头焦距确定其接收的视野范围。
由于剪裁区域适用于所有视频流,这些视频流的宽高比可能与剪裁区域的不同,所以每路视频流所用的实际传感器区域可能小于剪裁区域。具体而言,每路视频流应尽量避免进一步剪裁已定义的剪裁区域,以维持方形像素及其宽高比。如果视频流的宽高比大于剪裁区域,则该视频流应该在垂直方向上进一步剪裁,如果视频流的宽高比小于剪裁区域,则该视频流应该在水平方向上进一步剪裁。
在所有情况下,视频流剪裁均必须位于整个剪裁区域的中心位置,并且相对于整个剪裁区域,每路视频流要么在水平方向上进行剪裁,要么在垂直方向上进行剪裁,但绝不能在这两个方向上同时进行剪裁。
例如,如果两路视频流分别定义为 640x480(宽高比为 4:3)和 1280x720(宽高比为 16:9),并假设传感器为 300 万像素级(2000 x 1500 像素阵列),下面展示了针对几个样本剪裁区域,每路视频流的预期输出区域。
剪裁区域:(500、375、1000、750)(宽高比为 4:3)
640x480 视频流剪裁:(500、375、1000、750)(与剪裁区域相同)
1280x720 视频流剪裁:(500、469、1000、562)
图 1. 宽高比:4:3
剪裁区域:(500、375、1333、750)(宽高比为 16:9)
640x480 视频流剪裁:(666、375、1000、750)
1280x720 视频流剪裁:(500、375、1333、750)(与剪裁区域相同)
图 2. 宽高比:16:9
剪裁区域:(500、375、750、750)(宽高比为 1:1)
640x480 视频流剪裁:(500、469、750、562)
1280x720 视频流剪裁:(500、543、750、414)
图 3. 宽高比为 1:1
最后一个示例是宽高比为 1024×1024(方形)的视频流,而不是 480p 视频流:
剪裁区域:(500、375、1000、750)(宽高比为 4:3)
1024x1024 视频流剪裁:(625、375、750、750)
1280x720 视频流剪裁:(500、469、1000、562)
图 4. 宽高比为 4:3(方形)
重新处理
对原始图片文件提供额外的支持功能,即支持对 RAW Bayer 数据进行重新处理。该支持功能允许相机管道处理之前捕获的 RAW 缓冲区和元数据(之前记录的整个帧),以生成新渲染的 YUV 或 JPEG 输出。
缩放
对于搭载 Android 11 或更高版本的设备,应用可通过 ANDROID_CONTROL_ZOOM_RATIO
设置来使用镜头缩放(数字方式和光学方式)。
缩放比例定义为浮点因子。应用可以使用 ANDROID_CONTROL_ZOOM_RATIO
控制缩放级别,而不是使用 ANDROID_SCALER_CROP_REGION
进行剪裁和缩放;使用 ANDROID_SCALER_CROP_REGION
进行横向和垂直剪裁可使宽高比与本机相机传感器不同。
多摄像头系统可能包含多个具有不同焦距的镜头,并且用户可以通过在镜头之间进行切换来使用光学缩放。在以下情况下,使用 ANDROID_CONTROL_ZOOM_RATIO
具有以下优势:
- 从广角镜头变焦到长焦镜头:与
ANDROID_SCALER_CROP_REGION
的整数值相比,浮点比率可提供更高的精确度。
- 从广角镜头变焦到超广角镜头:
ANDROID_CONTROL_ZOOM_RATIO
支持缩小 (<1.0f),而 ANDROID_SCALER_CROP_REGION
不支持。
为进行说明,以下是对于上一部分中定义的相同假想镜头,采用不同缩放比例、剪裁区域和输出视频流的几种情况。
缩放比例:2.0;原始视野范围的 1/4
剪裁区域:(0、0、2000、1500)(宽高比为 4:3)
640x480 视频流剪裁:(0、0、2000、1500)(与剪裁区域相同)
1280x720 视频流剪裁:(0、187、2000、1125)
图 5. 缩放级别为 2.0,宽高比为 4:3
缩放比例:2.0;原始视野范围的 1/4
剪裁区域:(0、187、2000、1125)(宽高比为 16:9)
640x480 视频流剪裁:(250、187、1500、1125)(邮筒模式)
1280x720 视频流剪裁:(0、187、2000、1125)(与剪裁区域相同)
图 6. 缩放级别为 2.0,宽高比为 16:9
缩放比例:0.5;原始视野范围的 4 倍(从广角镜头切换到超广角镜头)
剪裁区域:(250、0、1500、1500)(宽高比为 1:1)
640x480 视频流剪裁:(250、187、1500、1125)(信箱模式)
1280x720 视频流剪裁:(250、328、1500、844)(信箱模式)
图 7. 缩放级别为 0.5,宽高比为 1:1
如上图所示,剪裁区域的坐标系会更改为有效的缩放后视野范围,用矩形和以下尺寸表示:(0
、0
、activeArrayWith
、activeArrayHeight
)。这同样适用于 AE/AWB/AF 区域和人脸。此坐标系更改不适用于 RAW 格式拍摄及其相关元数据,例如 intrinsicCalibration
和 lensShadingMap
。
我们仍以上述同一示例为例,假设输出视频流 #1 (640x480) 是取景器视频流,则可以通过以下两种设置来实现 2 倍缩放:
zoomRatio = 2.0
,scaler.cropRegion = (0, 0, 2000, 1500)
zoomRatio = 1.0
(默认),scaler.cropRegion = (500, 375, 1000, 750)
如需使应用将 android.control.aeRegions
设置为取景器视野范围的左上角,请将 android.control.aeRegions
设置为 (0, 0, 1000, 750)
,并将 android.control.zoomRatio
设置为 2.0
。或者,应用可以针对 1.0
的 android.control.zoomRatio
将 android.control.aeRegions
设置为 (500, 375, 1000, 750)
的同等区域。
本页面上的内容和代码示例受内容许可部分所述许可的限制。Java 和 OpenJDK 是 Oracle 和/或其关联公司的注册商标。
最后更新时间 (UTC):2025-03-26。
[[["易于理解","easyToUnderstand","thumb-up"],["解决了我的问题","solvedMyProblem","thumb-up"],["其他","otherUp","thumb-up"]],[["没有我需要的信息","missingTheInformationINeed","thumb-down"],["太复杂/步骤太多","tooComplicatedTooManySteps","thumb-down"],["内容需要更新","outOfDate","thumb-down"],["翻译问题","translationIssue","thumb-down"],["示例/代码问题","samplesCodeIssue","thumb-down"],["其他","otherDown","thumb-down"]],["最后更新时间 (UTC):2025-03-26。"],[],[],null,["# Output streams, cropping, and zoom\n\nOutput streams\n--------------\n\nThe camera subsystem operates solely on the ANativeWindow-based pipeline for\nall resolutions and output formats. Multiple streams can be configured at\none time to send a single frame to many targets such as the GPU, the video\nencoder,\n[RenderScript](/docs/core/architecture/vndk/renderscript),\nor app-visible buffers (RAW Bayer, processed YUV\nbuffers, or JPEG-encoded buffers).\n\nAs an optimization, these output streams must be configured ahead of time, and\nonly a limited number may exist at once. This allows for pre-allocation of\nmemory buffers and configuration of the camera hardware, so that when requests\nare submitted with multiple or varying output pipelines listed, there won't be\ndelays or latency in fulfilling the request.\n\nFor further information about the guaranteed stream output combinations\nthat depend on the supported hardware level, see\n[createCaptureSession()](https://developer.android.com/reference/android/hardware/camera2/CameraDevice#createCaptureSession(java.util.List%3Candroid.view.Surface%3E,%20android.hardware.camera2.CameraCaptureSession.StateCallback,%20android.os.Handler)).\n\nCropping\n--------\n\nCropping of the full pixel array (for digital zoom and other use cases where a\nsmaller FOV is desirable) is communicated through the ANDROID_SCALER_CROP_REGION\nsetting. This is a per-request setting, and can change on a per-request basis,\nwhich is critical for implementing smooth digital zoom.\n\nThe region is defined as a rectangle (x, y, width, height), with (x, y)\ndescribing the top-left corner of the rectangle. The rectangle is defined on the\ncoordinate system of the sensor active pixel array, with (0,0) being the\ntop-left pixel of the active pixel array. Therefore, the width and height cannot\nbe larger than the dimensions reported in the ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY\nstatic info field. The minimum allowed width and height are reported by the HAL\nthrough the ANDROID_SCALER_MAX_DIGITAL_ZOOM static info field, which describes\nthe maximum supported zoom factor. Therefore, the minimum crop region width and\nheight are: \n\n```\n {width, height} =\n { floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[0] /\n ANDROID_SCALER_MAX_DIGITAL_ZOOM),\n floor(ANDROID_SENSOR_ACTIVE_PIXEL_ARRAY[1] /\n ANDROID_SCALER_MAX_DIGITAL_ZOOM) }\n```\n\nIf the crop region needs to fulfill specific requirements (for example, it needs\nto start on even coordinates, and its width/height needs to be even), the HAL\nmust do the necessary rounding and write out the final crop region used in the\noutput result metadata. Similarly, if the HAL implements video stabilization, it\nmust adjust the result crop region to describe the region actually included in\nthe output after video stabilization is applied. In general, a camera-using\napp must be able to determine the field of view it is receiving based on\nthe crop region, the dimensions of the image sensor, and the lens focal length.\n\nSince the crop region applies to all streams, which may have different aspect\nratios than the crop region, the exact sensor region used for each stream may be\nsmaller than the crop region. Specifically, each stream should maintain square\npixels and its aspect ratio by minimally further cropping the defined crop\nregion. If the stream's aspect ratio is wider than the crop region, the stream\nshould be further cropped vertically, and if the stream's aspect ratio is\nnarrower than the crop region, the stream should be further cropped\nhorizontally.\n\nIn all cases, the stream crop must be centered within the full crop region, and\neach stream is only either cropped horizontally or vertical relative to the full\ncrop region, never both.\n\nFor example, if two streams are defined, a 640x480 stream (4:3 aspect), and a\n1280x720 stream (16:9 aspect), below demonstrates the expected output regions\nfor each stream for a few sample crop regions, on a hypothetical 3 MP (2000 x\n1500 pixel array) sensor.\n\n\nCrop region: (500, 375, 1000, 750) (4:3 aspect ratio) \n\n640x480 stream crop: (500, 375, 1000, 750) (equal to crop region) \n\n1280x720 stream crop: (500, 469, 1000, 562)\n\n\n**Figure 1.** 4:3 aspect ratio\n\nCrop region: (500, 375, 1333, 750) (16:9 aspect ratio) \n\n640x480 stream crop: (666, 375, 1000, 750) \n\n1280x720 stream crop: (500, 375, 1333, 750) (equal to crop region)\n\n\n**Figure 2.** 16:9 aspect ratio\n\nCrop region: (500, 375, 750, 750) (1:1 aspect ratio) \n\n640x480 stream crop: (500, 469, 750, 562) \n\n1280x720 stream crop: (500, 543, 750, 414)\n\n\n**Figure 3.** 1:1 aspect ratio\n\n\nAnd a final example, a 1024x1024 square aspect ratio stream instead of the 480p\nstream: \n\nCrop region: (500, 375, 1000, 750) (4:3 aspect ratio) \n\n1024x1024 stream crop: (625, 375, 750, 750) \n\n1280x720 stream crop: (500, 469, 1000, 562)\n\n\n**Figure 4.** 4:3 aspect ratio, square\n\nReprocessing\n------------\n\nAdditional support for raw image files is provided by reprocessing support for RAW Bayer\ndata. This support allows the camera pipeline to process a previously captured\nRAW buffer and metadata (an entire frame that was recorded previously), to\nproduce a new rendered YUV or JPEG output.\n\nZoom\n----\n\nFor devices running Android 11 or higher, an app can use a camera's zoom\n(digital and optical) through the `ANDROID_CONTROL_ZOOM_RATIO` setting.\n\nThe zoom ratio is defined as a floating point factor. Instead of\nusing `ANDROID_SCALER_CROP_REGION` for crop and zoom, an app can use\n`ANDROID_CONTROL_ZOOM_RATIO` to control the zoom level, and use\n`ANDROID_SCALER_CROP_REGION` for horizontal and vertical cropping to\nachieve aspect ratios different than the native camera sensor.\n\nA multi-camera system may contain more than one lens with different\nfocal lengths, and the user can use optical zoom by switching between lenses.\nUsing `ANDROID_CONTROL_ZOOM_RATIO` has benefits in the scenarios below:\n\n- Zooming in from a wide lens to a telephoto lens: A floating point ratio provides better precision compared to integer values of `ANDROID_SCALER_CROP_REGION`.\n- Zooming out from a wide lens to an ultrawide lens: `ANDROID_CONTROL_ZOOM_RATIO` supports zoom-out (\\\u003c1.0f) whereas `ANDROID_SCALER_CROP_REGION` doesn't.\n\n\u003cbr /\u003e\n\n\u003cbr /\u003e\n\nTo illustrate, here are several scenarios of different zoom ratios, crop regions, and output streams, using the same hypothetical camera defined in the previous section.\n\n\u003cbr /\u003e\n\n\nZoom ratio: 2.0; 1/4 of original field of view \n\nCrop region: (0, 0, 2000, 1500) (4:3 aspect ratio) \n\n640x480 stream crop: (0, 0, 2000, 1500) (equal to crop region) \n\n1280x720 stream crop: (0, 187, 2000, 1125)\n\n\n**Figure 5.** 2.0 zoom, 4:3 aspect ratio\n\nZoom ratio: 2.0; 1/4 of original field of view \n\nCrop region: (0, 187, 2000, 1125) (16:9 aspect ratio) \n\n640x480 stream crop: (250, 187, 1500, 1125) (pillarboxed) \n\n1280x720 stream crop: (0, 187, 2000, 1125) (equal to crop region)\n\n\n**Figure 6.** 2.0 zoom, 16:9 aspect ratio\n\nZoom ratio: 0.5; 4x of original field of view (switched from wide lens to ultrawide lens) \n\nCrop region: (250, 0, 1500, 1500) (1:1 aspect ratio) \n\n640x480 stream crop: (250, 187, 1500, 1125) (letterboxed) \n\n1280x720 stream crop: (250, 328, 1500, 844) (letterboxed)\n\n\n**Figure 7.** 0.5 zoom, 1:1 aspect ratio\n\nAs seen from the graphs above, the coordinate system of the crop region changes to the effective\nafter-zoom field of view, and is represented by the rectangle with the following dimensions:\n(`0`, `0`, `activeArrayWith`, `activeArrayHeight`).\nThe same applies to AE/AWB/AF regions and faces. This coordinate system change doesn't apply to\nRAW capture and its related metadata such as `intrinsicCalibration` and\n`lensShadingMap`.\n\nUsing the same hypothetical example above, and assuming output stream #1 (640x480) is the\nviewfinder stream, 2.0x zoom can be achieved in one of two ways:\n\n- `zoomRatio = 2.0`, `scaler.cropRegion = (0, 0, 2000, 1500)`\n- `zoomRatio = 1.0` (default), `scaler.cropRegion = (500, 375, 1000, 750)`\n\nFor an app to set `android.control.aeRegions` to be the top-left\nquarter of the viewfinder field of view, set\n`android.control.aeRegions` to `(0, 0, 1000, 750)` with\n`android.control.zoomRatio` set to `2.0`. Alternatively,\nthe app can set `android.control.aeRegions` to the equivalent\nregion of `(500, 375, 1000, 750)` for\n`android.control.zoomRatio` of `1.0`."]]