Chapter 125: Apple Camera Capture Pipeline
本章讨论 Apple 平台上一条相机请求怎样从 App 的 AVCaptureSession 走到帧回调、照片回调或视频文件输出。读完后,读者应能追踪一个相机现象属于 App 配置、AVFoundation 会话图、Core Media 帧表达、系统媒体服务、驱动/ISP 或传感器边界中的哪一段,并能解释公开 API 暴露的部分与 Apple 私有硬件路径之间的分界。
贯穿本章的材料是一类常见 App 行为:用户打开自定义相机页面,页面显示预览,点击快门保存一张照片,同时可能把同一组视频帧写入短视频文件。这个行为看起来像 App 直接使用摄像头,实际路径由 AVCaptureSession 组织输入输出,由 AVCaptureDevice 表达物理或逻辑相机,由 AVCapturePhotoOutput、AVCaptureVideoDataOutput、AVAssetWriter 等对象接收结果,再由系统媒体服务、驱动、ISP 和传感器完成硬件控制与图像处理。
Apple 相机栈的核心约束是公开 API 主要表达“请求意图”和“结果对象”,硬件调度、ISP 处理、部分多帧融合和设备级算法位于公开 API 之外。工程判断时要把公开文档、可观察回调、错误码、Instruments/Console 证据和合理推断分开使用。可以确定的是 API 入口、对象关系和回调语义;需要保守表述的是系统 daemon 内部实现、私有驱动细节、ISP 固件策略和具体算法流水线。
125.1 Apple Camera Stack 总路径
Apple Camera Stack 可以从 App 可见行为开始拆解:App 请求权限,创建会话,选择设备,添加输入和输出,启动 session,接收预览帧、照片结果或视频样本。公开层面的入口集中在 AVFoundation 的 camera capture API,例如 AVCaptureSession、AVCaptureDevice、AVCaptureInput、AVCaptureOutput 以及若干具体 output 类型。
这条路径可以写成一个责任链:App 表达拍摄意图;AVFoundation 把意图整理成 session graph;系统媒体服务持有设备、仲裁资源并连接底层驱动;驱动和固件控制 sensor、lens、OIS、ISP 和内存 buffer;结果以 CMSampleBuffer、CVPixelBuffer、photo data、metadata 或文件写入状态返回到 App。App 的代码接触的是公开对象,系统内部执行的是设备控制、buffer 交换、时间戳同步和图像处理。
这张图的边界在于它描述公开可推断的系统路径,图中的 System media service 代表 Apple 平台负责媒体设备协调的系统侧组件集合。具体 daemon 名称、进程拆分和私有驱动接口并非稳定公开契约,因此正文只把它们作为责任层级处理。对 App 开发者来说,稳定可依赖的是 AVFoundation 对象模型、权限状态、回调、通知、错误码和性能观测。
贯穿示例中的预览、拍照和录制都复用同一条上行路径,但输出落点不同。预览通常进入 AVCaptureVideoPreviewLayer 或视频帧 output;拍照进入 AVCapturePhotoOutput 的 delegate;视频录制可以走 AVCaptureMovieFileOutput,也可以走 AVCaptureVideoDataOutput 加 AVAssetWriter。这些分支共享设备和 session,差异出现在 output 类型、buffer 格式、时间戳处理、编码链路和回调时机。
125.2 AVFoundation 作为 Camera Framework Frontend
AVFoundation 在相机路径中承担 frontend 角色:它让 App 用对象表达设备选择、session 配置、输入输出、权限和回调,同时隐藏硬件驱动、ISP 调度和系统服务连接。这里的 frontend 指“稳定 API 表面”,它接收 App 的配置请求,把请求转换成系统可调度的相机会话,并把结果包装成 Core Media 或 AVFoundation 对象返回。
相机权限是 frontend 路径的第一道用户授权边界。App 需要在 Info.plist 中提供 NSCameraUsageDescription,再通过 AVCaptureDevice authorizationStatus 与请求授权 API 处理授权状态。权限通过后,App 仍然需要构造合法 session graph;权限解决“谁可以请求硬件”,session graph 解决“请求哪些设备、以什么格式、输出到哪里”。
一个最小相机页面通常包含以下阶段:查询可用设备,创建 AVCaptureDeviceInput,把 input 和 output 加入 AVCaptureSession,提交配置,启动 session,接收 output 回调。配置过程应放在专用串行队列中管理,因为 session 的启动、停止和图形修改会涉及系统资源分配,放在主线程会扩大 UI 卡顿风险。
let session = AVCaptureSession()
session.beginConfiguration()
session.sessionPreset = .photo
let device = AVCaptureDevice.default(.builtInWideAngleCamera, for: .video, position: .back)!
let input = try AVCaptureDeviceInput(device: device)
let photoOutput = AVCapturePhotoOutput()
if session.canAddInput(input) {
session.addInput(input)
}
if session.canAddOutput(photoOutput) {
session.addOutput(photoOutput)
}
session.commitConfiguration()
session.startRunning()
这段代码展示的关键点是:App 并未直接打开 sensor。AVCaptureDevice.default 只是选择公开设备对象;AVCaptureDeviceInput 把设备包装成 session 的输入节点;AVCapturePhotoOutput 声明照片结果的接收端;startRunning 才触发系统侧资源打开和流启动。canAddInput 与 canAddOutput 是配置合法性检查,失败时通常说明设备、preset、输出组合或当前资源状态冲突。
Frontend 的另一个职责是把错误压缩成 App 可处理的事件。常见信号包括 session runtime error notification、interruption notification、权限状态变化、设备连接变化和 output delegate 错误。App 处理这些信号时,应先判断错误属于授权、资源抢占、媒体服务重置、配置不兼容、磁盘写入还是编码失败,再决定提示用户、重建 session、降级输出或释放资源。
125.3 AVCaptureSession、AVCaptureDevice、AVCaptureInput、AVCaptureOutput
AVCaptureSession 是 Apple 相机公开模型里的会话图所有者。会话图由输入、输出和连接组成,表达“从哪个设备采集、经过哪些输出、交付给哪些消费者”。AVCaptureDevice 表示可被系统枚举和配置的捕获设备;AVCaptureInput 把设备接入 session;AVCaptureOutput 表示结果端,例如 photo、video data、metadata、movie file 或 depth data。
这个对象模型的关键价值是把硬件能力转换成可检查的配置组合。App 查询设备时看到的是 position、device type、format、frame rate、focus、exposure、zoom、torch、system pressure 等公开属性;session 提交时系统检查这些属性能否与当前 preset、output、连接和其他 App 资源占用共同成立。通过 AVCaptureDevice.Format 选择格式时,App 实际在约束分辨率、像素格式、最大帧率、HDR、深度、稳定、编码链路和带宽需求。
Session graph 可以理解成四类边:device 到 input 的边,input 到 output 的 connection,output 到 App delegate 或 layer 的回调边,以及 session 到系统服务的资源边。App 能直接修改前三类公开边;最后一类由系统根据权限、硬件状态、温控、后台策略和资源仲裁执行。分析问题时要把“图配置成功”和“硬件持续稳定输出”分开检查。
下面的表格把对象和责任边界压缩成同一组维度,便于把贯穿示例中的预览、拍照和视频录制放回系统路径中。
| 对象 | App 可配置内容 | 系统负责内容 | 典型失败表现 |
|---|---|---|---|
AVCaptureSession | preset、输入输出、启动停止、事务配置 | 会话资源提交、运行状态、interruption、runtime error | startRunning 后无画面、runtime error、会话被中断 |
AVCaptureDevice | 选择相机、format、focus、exposure、zoom、torch | 设备枚举、硬件状态、system pressure、物理能力映射 | 不支持某格式、镜头切换失败、压力升高导致降级 |
AVCaptureInput | 把 device 接入 session | 验证设备能否进入当前会话 | canAddInput 返回 false |
AVCaptureOutput | 选择 photo/video/data/file 输出和回调队列 | 输出组合验证、buffer 交付、编码或照片处理连接 | 回调延迟、输出格式不匹配、保存失败 |
AVCaptureConnection | 方向、稳定、镜像、启停部分连接 | 连接合法性和可用能力 | 预览方向错、稳定效果缺失、连接不可用 |
beginConfiguration 和 commitConfiguration 体现了 session graph 的事务边界。App 在事务内修改 input、output、preset 和连接属性,系统在提交时一次性验证组合并更新运行图。这个边界对排查很实用:配置期错误优先看 canAddInput、canAddOutput 和 preset 支持;运行期错误优先看 notification、interruption reason、system pressure 和 output delegate 错误。
预览层也是 session graph 的消费者。AVCaptureVideoPreviewLayer 通过 session 接收视频流并交给 Core Animation 合成显示,它服务用户取景,不等同于照片最终输出。照片输出可能触发不同的分辨率、多帧处理、RAW/processed 分支和 metadata 写入;因此预览清晰度、照片质量和视频编码质量需要分别定位。
125.4 Core Media Sample Buffer 与 Camera Frame 表达
Core Media 负责把时间相关的媒体样本表示成可传递对象。相机视频帧常见形式是 CMSampleBuffer,它携带样本数据、时间信息、格式描述和附件;像素内容通常由 CVPixelBuffer 表示;格式细节由 CMFormatDescription 说明。这里的 frame 表达包含两层含义:一层是图像内存,另一层是这块图像在媒体时间轴上的位置和解释方式。
在贯穿示例中,视频预览和录制使用的是连续帧。每一帧到达 App 时,App 需要知道它的像素格式、宽高、色彩信息、时间戳、方向、相机内参或额外 metadata。CVPixelBuffer 解决“图像数据在哪里以及如何访问”;CMSampleBuffer 解决“这张图像属于哪个采集时刻、用什么格式解释、带有哪些附件”。录制、实时滤镜、机器视觉和帧同步都依赖这两个对象的边界。
func captureOutput(
_ output: AVCaptureOutput,
didOutput sampleBuffer: CMSampleBuffer,
from connection: AVCaptureConnection
) {
guard let pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else {
return
}
let presentationTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
let format = CMSampleBufferGetFormatDescription(sampleBuffer)
processFrame(pixelBuffer: pixelBuffer,
presentationTime: presentationTime,
formatDescription: format)
}
这段 delegate 代码说明 App 接收的并非抽象“相机帧”,而是带时间和格式的媒体样本。presentationTime 用于和音频、编码器、写文件链路对齐;formatDescription 用于确认像素格式、尺寸和色彩相关信息;pixelBuffer 是图像处理和编码的直接输入。实时处理失败时,先检查回调队列是否阻塞,再检查像素格式转换、buffer 生命周期、时间戳连续性和下游编码写入速度。
Sample buffer 的附件是相机系统向 App 传递附加事实的重要通道。附件可能描述曝光、相机校准、颜色空间、深度或其他输出相关信息,具体可用项依赖 output 类型、设备能力和系统版本。App 可以读取公开附件,但要把它们当作当前输出的一部分证据,而非私有 ISP 决策的完整记录。
Core Media 帧表达也解释了预览掉帧与照片质量之间的边界。预览和视频 data output 依赖连续低延迟帧,系统在压力升高时可能降低帧率、延迟回调或让 App 丢弃过期帧;照片输出更重视单次 capture 的完整处理,可能经历额外的照片管线、metadata 整理和多帧融合。排查时要分别记录帧时间戳、output 回调间隔、CPU/GPU/编码耗时和 session interruption。
125.5 Photo Capture Pipeline 与 AVPhotoOutput
照片管线由 AVCapturePhotoOutput 和 AVCapturePhotoSettings 表达一次 capture 请求。它覆盖 capture settings、processed output、RAW output、bracket、flash、quality prioritization、metadata 和 delegate callback。与连续视频帧相比,照片请求更像一次有状态事务:App 提交拍摄参数,系统根据设备能力和当前 session graph 触发采集与处理,最后通过 delegate 回传结果或错误。
照片请求的输入是 settings,输出是 AVCapturePhoto 及其数据、metadata 和相关回调。settings 里可以表达格式、codec、flash、preview photo、RAW/processed 组合、photo quality prioritization 等公开选项。系统内部会把这些选项和设备 format、当前曝光/对焦状态、ISP 能力、内存带宽、温控状态和用户授权状态一起检查。公开 API 暴露的是请求和结果,图像处理算法细节属于 Apple 平台实现。
let settings = AVCapturePhotoSettings()
settings.flashMode = .auto
photoOutput.capturePhoto(with: settings, delegate: photoDelegate)
这段最小代码展示了 photo capture 的事务入口。capturePhoto 发起一次照片请求,delegate 接收捕获开始、处理进度、最终照片数据、错误和结束信号。真实工程里通常还会处理 orientation、preview pixel format、RAW/processed 格式、Live Photo、depth data、semantic segmentation matte、photo quality prioritization 和保存路径。
照片 delegate 的价值在于把一次拍照拆成可观察阶段。App 可以观察 capture 是否开始、处理是否完成、是否产生 photo data、metadata 是否完整、是否出现错误。保存到相册还会进入 Photos 权限和写入路径;这属于照片结果之后的存储授权问题,应和相机捕获路径分开定位。
Photo pipeline 的性能边界和视频不同。照片可能需要更高分辨率、更复杂的 ISP/计算摄影处理和更多 metadata 整理,回调延迟高于预览帧属于正常设计范围。用户看到的快门反馈、预览冻结、拍照结果到达和相册保存完成是四个不同时间点;App 设计应分别处理 UI 状态、capture 请求状态、photo 处理状态和持久化状态。
RAW 与 processed 的边界也要用公开 API 表达。RAW 输出更接近传感器数据的可处理结果,processed 输出经过系统照片管线形成 JPEG、HEIF 或其他格式。即使使用 RAW,sensor readout、black level、demosaic 前后的可见信息、ISP 参与程度和私有校正也受 Apple 设备与系统控制。工程结论应写成“RAW 提供更大的后期空间和不同的数据路径”,并明确系统影像管线仍然约束输出边界。
125.6 Video Capture Pipeline 与 AVAssetWriter / VideoToolbox 连接
视频捕获路径关注连续帧、编码、文件容器和音画同步。App 可以使用 AVCaptureMovieFileOutput 获得较高层的文件录制能力,也可以使用 AVCaptureVideoDataOutput 接收 CMSampleBuffer,再用 AVAssetWriter 或 VideoToolbox VTCompressionSession 连接编码与封装。后者控制力更高,也要求 App 自己处理时间戳、背压、队列和失败恢复。
贯穿示例里的“预览同时录短视频”可以拆成三条并行消费者:preview layer 用于显示,video data output 用于拿帧,audio data output 或音频输入用于声音,asset writer 用于文件。关键判断是所有消费者共享同一个 capture session 和设备资源,任何一个消费者处理过慢都可能扩大延迟、丢帧或写入失败。
if assetWriter.status == .unknown {
assetWriter.startWriting()
assetWriter.startSession(atSourceTime: presentationTime)
}
if videoInput.isReadyForMoreMediaData {
videoInput.append(sampleBuffer)
}
这段简化代码说明文件写入依赖媒体时间轴。startSession(atSourceTime:) 把写入 session 的起点绑定到第一帧时间,后续 video sample 和 audio sample 按各自 timestamp 进入 writer input。音画同步问题通常来自 timestamp 基准不一致、音频早于视频启动、队列阻塞、编码器背压或丢帧策略错误。
VideoToolbox 位于更底层的压缩接口边界。App 通过 VTCompressionSession 可以控制编码参数、码率、profile、关键帧间隔和硬件编码倾向,但输入仍然是 Core Video/Core Media 表达的帧,输出仍然要进入封装或网络发送路径。硬件编码器是否可用、具体编码器调度和功耗策略受设备、系统版本和当前资源压力影响。
视频路径的失败通常有五类。第一类是 capture 层失败,例如权限、session interruption 或设备不可用。第二类是帧处理失败,例如回调队列阻塞、像素格式转换过慢或 buffer 生命周期错误。第三类是编码失败,例如格式不支持、硬件编码资源受限或 VideoToolbox 返回错误。第四类是写文件失败,例如磁盘空间、文件权限或 writer 状态错误。第五类是同步失败,例如音频和视频时间轴未对齐。排查顺序应按 capture → sample buffer → encoder → writer → file 逐层收敛。
视频管线也要考虑 system pressure。AVCaptureDevice.SystemPressureState 暴露系统压力信号,压力升高时 App 可以降低分辨率、帧率或输出组合,给用户保留可用录制体验。这里的降级属于 App 对公开信号的响应;具体热管理、硬件资源调度和 ISP 降载策略由系统执行。
125.7 Hardware ISP、Photo Processing 与 Apple 封闭硬件路径
Apple 相机体验高度依赖封闭硬件与系统照片管线。公开 API 能选择设备、格式、输出和部分质量偏好;硬件 ISP、Neural Engine 参与的计算摄影、传感器校正、多帧融合、降噪、HDR、肤色与色彩处理、OIS/EIS 协同和镜头切换策略多数处于私有实现边界。正文中把这部分称为封闭硬件路径,含义是 App 可以观察输入输出和公开控制点,但无法以稳定公开接口枚举完整内部流水线。
这个边界对工程判断很关键。第三方 App 调用 AVCapturePhotoOutput 得到系统提供的照片处理结果,但并不等于获得默认相机 App 的全部私有能力组合。默认相机 App、系统框架和硬件管线之间可能使用更深层的设备级策略;第三方 App 能依赖的是公开 AVFoundation 能力、设备 format、photo settings、metadata 和系统声明的功能。涉及无法验证的内部算法时,应写成基于公开行为的推断。
Hardware ISP 的作用可以从输入输出角度理解。输入是 sensor 的原始电信号和读出数据,外加镜头、曝光、对焦、白平衡、运动传感器和时间信息;处理包括坏点校正、黑电平、去马赛克、降噪、锐化、色彩变换、HDR 合成、局部 tone mapping、稳定和多帧融合等阶段;输出是供预览、照片、视频编码或机器视觉使用的图像 buffer、metadata 和时间戳。具体阶段顺序和算法参数由设备与系统实现决定。
封闭路径并不意味着工程上无法定位问题。App 可以用公开证据把问题缩小到边界附近。例如预览帧正常但照片偏色,优先检查 photo settings、白平衡锁定、format、HDR/quality prioritization 和 metadata;视频正常但照片处理延迟异常,优先检查 photo output 回调时间、系统压力、内存压力和同时输出组合;同一代码在不同 iPhone 型号上成像差异明显,优先检查设备 format、镜头选择、传感器尺寸、系统版本和公开可用能力,再把剩余差异归入设备级 ISP/算法策略。
Apple 的公开材料也经常强调计算摄影、Photonic Engine、Deep Fusion、Smart HDR、Night mode 等用户可见能力。这些名称说明平台有设备级图像处理能力,也说明第三方 App 需要通过公开 AVFoundation 能力间接获得系统处理结果。写技术文档时应把产品能力、公开 API 和私有实现分层:产品能力描述用户体验,公开 API 描述 App 能请求什么,私有实现描述系统可能如何完成但缺少稳定契约。
125.8 Apple Camera Path:App → AVFoundation → System Service / Daemon → Driver / ISP → Sensor
把 Apple Camera Path 还原成可排查路径时,应使用“公开文档 + 可观察工具 + 错误码 + 行为推断”的组合。公开文档负责确认 API 对象和回调契约;Instruments 负责观察 CPU、GPU、memory、thermal、time profiler 和 signpost;Console 负责观察 App 日志、系统级提示和崩溃/错误上下文;错误码和 notification 负责判断 session interruption、media services reset、设备不可用或写入失败。
路径复盘可以按固定顺序执行。第一步检查授权和 Info.plist,确认 App 有相机权限且用户授权状态正确。第二步检查 session graph,确认 input、output、preset、format 和 connection 组合可以提交。第三步检查运行信号,观察 session 是否启动、是否收到 interruption、runtime error 或 system pressure。第四步检查 output 回调,确认 photo delegate、video data delegate 或 writer 状态是否符合预期。第五步检查用户可见结果,例如预览黑屏、快门无响应、照片保存失败、录制丢帧或音画不同步。
这张流程图给出排查顺序,也给出责任主体。权限失败属于用户授权和系统隐私策略;图配置失败属于 App 与 AVFoundation 能力匹配;运行中断属于系统服务资源仲裁或媒体服务状态;回调延迟属于 output 队列、系统压力或下游处理;保存失败属于文件、Photos 权限或编码封装路径。
Instruments 的价值是把“感觉卡”变成可定位证据。Time Profiler 可以看帧处理函数是否占用过多 CPU;Allocations 和 memory graph 可以看 pixel buffer、image conversion 和缓存是否增长;Energy Log 与 thermal 相关观察可以解释长时间预览或录制后的系统压力;os_signpost 可以把 App 的 capture start、first frame、photo processed、writer append 和 save completed 标成同一条时间线。工具输出只提供证据,结论仍要回到责任链。
Console 和错误码适合还原系统边界附近的问题。遇到 AVErrorMediaServicesWereReset 这类公开错误时,App 应重建或恢复 session,并把当前 capture 状态回滚到可重新请求的状态。遇到 session interruption 时,应根据 reason 判断是否有其他客户端占用、系统资源受限或前后台状态变化。遇到 output delegate 错误时,应保存 settings、format、timestamp、writer status 和当前系统压力,形成可复现的最小输入。
下面用贯穿示例收束一次完整复盘:用户打开相机页后黑屏,但点击拍照也没有照片回调。排查时先看授权状态和 NSCameraUsageDescription;授权正常则看 session graph 的 canAddInput、canAddOutput 和 commitConfiguration;图提交正常则观察 isRunning、runtime error notification 和 interruption;session 正常运行但无预览时检查 preview layer 是否绑定 session、layer frame 是否有效、connection 是否 enabled;预览正常但无照片回调时检查 AVCapturePhotoOutput 是否在 session 中、delegate 是否被释放、settings 是否支持当前 output、回调队列是否阻塞。这个顺序把问题从“相机坏了”拆成可验证的系统路径。
Apple Camera Path 的最终判断是:App 负责表达意图、配置公开会话图、处理回调和降级;AVFoundation 负责把意图转换成系统可执行的 session;系统服务负责资源持有、权限检查后的运行仲裁和错误通知;driver/ISP/sensor 负责硬件采集、图像处理和时间同步。越靠近硬件,公开信息越少;越靠近 App,证据越可控。稳定的工程写法是沿着责任链逐层收集证据,并在私有边界前停止过度断言。
最小自检任务
你正在排查一个 iPhone 自定义相机页:页面能显示预览,点击拍照后 UI 有快门动画,但没有收到最终照片数据;同一 session 中的视频帧回调仍然持续到达。请写出从 App 到 Apple Camera Stack 的排查路径,说明每一步对应的责任主体、需要检查的公开证据、可能的资源边界和用户可见结果。
答案要点
应先把现象分层:预览正常和视频帧持续到达,说明权限、设备打开、session 运行和基础视频流大概率成立;没有最终照片数据,把重点收敛到 AVCapturePhotoOutput 配置、photo settings、delegate 生命周期、photo output 回调队列、照片处理阶段和保存阶段。第一步检查 App 层:AVCapturePhotoOutput 是否已经加入当前 session,capturePhoto(with:delegate:) 是否实际调用,delegate 是否被强引用,UI 快门动画是否绑定到真实 capture 请求。第二步检查 AVFoundation 层:当前 preset、device format、photo settings、RAW/processed 组合、flash、quality prioritization 是否被当前设备和 output 支持。第三步检查运行信号:是否出现 runtime error、interruption、system pressure 或 media services reset。第四步区分 capture 结果与保存结果:如果 delegate 产生 AVCapturePhoto 但相册没有文件,应转向 Photos 权限和存储写入;如果 delegate 完全没有最终数据,应继续检查 photo output 事务和系统照片处理状态。最终结论应写成:视频 sample buffer 正常证明连续视频输出路径成立;照片路径还需要经过 AVCapturePhotoOutput 的 settings 验证、系统照片处理和 delegate 完成回调,二者属于不同 output 事务。
本章知识点总结
- 总路径:Apple 相机请求从 App 的 AVFoundation 配置进入系统媒体服务,再经过驱动、ISP 和 sensor,结果以 buffer、photo 或文件状态返回。
- 公开边界:AVFoundation 暴露设备、session、input、output、connection、回调和错误,私有 daemon、驱动和 ISP 细节属于非公开实现边界。
- 权限入口:相机权限决定 App 是否可以请求硬件,session graph 决定请求哪些设备和输出组合。
- 会话图:
AVCaptureSession持有输入、输出和连接,beginConfiguration与commitConfiguration构成配置事务边界。 - 设备对象:
AVCaptureDevice把物理或逻辑相机包装成可查询、可配置、可受系统压力约束的公开对象。 - 帧表达:
CMSampleBuffer表达带时间轴的媒体样本,CVPixelBuffer表达图像内存,二者共同支撑预览、处理和编码。 - 照片事务:
AVCapturePhotoOutput把一次拍照表达成 settings、系统处理、delegate callback 和 photo data 的事务。 - 视频链路:视频录制需要连续 sample buffer、编码器、writer input、时间戳和文件容器共同成立。
- ISP边界:ISP、Neural Engine 参与的计算摄影和设备级调校主要属于 Apple 封闭实现,正文只能基于公开 API 与可观察行为推断。
- 工具证据:Instruments、Console、notification、错误码和 App signpost 可以帮助定位责任层级,工具输出需要回到系统路径中解释。
- 排查顺序:稳定排查顺序是授权、session graph、运行状态、output 回调、编码或保存、用户可见结果。
- 照片视频差异:预览或视频帧正常只证明连续视频路径成立,照片仍要经过 photo settings、照片处理和最终 delegate 回调。