已验证 创建 2026/07/15 更新 2026/07/15

记录 MT8391 相机 HEIF 照片分辨率降级问题闭环复盘 的问题现象、排查过程、修改方案和验证方法。

MT8391 相机 HEIF 照片分辨率降级问题闭环复盘

闭环状态:已解决并验证通过
闭环日期:2026-07-15
问题类别:相机 pipeline / HAL 静态 metadata 配置 / App 与编码能力交互
平台:MT8391(MT8189 camera platform)
Camera Sensor:S5K3M5SX

一、问题定义(Problem Definition)

1. 问题现象

相机照片格式设置为 JPEG 时,照片大小选项与成片分辨率一致;切换为 HEIF 后,选择相机设置中的 13M 尺寸拍照,最终照片却只有约 0.8M,图库显示为 720×1080

复现日志表明 Camera App 实际保存的设置尺寸为 4415×2943(13M、3:2),并非最初口头描述的 4415×3072。横向编码尺寸是 1080×720,照片旋转后在图库中显示为 720×1080

2. 影响范围

项目影响
功能模块MTK Camera App、Camera HAL stream configuration、HEIF Encoder
受影响格式HEIF/HEIC
受影响尺寸S5K3M5SX metadata 中的 13M 3:2:4415×2943
用户可见结果设置为 13M,实际成片降为约 0.8M
根因层级Vendor/平台静态 metadata 配置
风险App 设置值、HAL Surface 和最终文件尺寸不一致

3. 问题分层

  1. 首要层级:Vendor 静态 metadata。 Sensor 输出尺寸被声明为奇数,违反 YUV420/HEIF 对齐约束。
  2. 后续处理层级:Camera App。 App 正确识别出奇数 HEIC 尺寸不可用,降级到同为 3:2 的 1080×720
  3. 结果执行层级:Camera HAL 与 C2 HEIF Encoder。 两者按 App 已降级后的尺寸正常工作,不是最先出错的层级。

二、关键信号提取(Signal Extraction)

问题日志:

C:\Users\PC\camear_heif.txt

1. 第一现场

Camera App 读取到的用户设置值:

07-15 03:33:47.320 I CamAp_PhotoDevice2Controller: [updatePreviewSize] :4415x2943
07-15 03:33:47.324 I CamAp_PhotoDevice2Controller: [updatePictureSize] :4415x2943

App 枚举 HEIC 输出能力后发现该尺寸为奇数:

07-15 03:33:47.328 I CamAp_PhotoDevice2Controller: [getBestHeicOutputSize] support HEIC size = 4415x2943
07-15 03:33:47.328 W CamAp_PhotoDevice2Controller: [getBestHeicOutputSize] ignore odd HEIC size = 4415x2943

这是本问题的第一有效异常。它证明问题不是拍照完成后被图库压缩,而是在创建 HEIF 输出流之前,目标尺寸就被判定为非法。

随后 App 明确执行尺寸替换:

07-15 03:33:47.328 W CamAp_PhotoDevice2Controller: [getBestHeicOutputSize] replace unsupported HEIC size 4415x2943 with 1080x720

请求尺寸和实际目标尺寸已经分离:

07-15 03:33:47.339 I CamAp_PhotoDevice2Controller: [setPictureSize] get current captureType = heif format = 1212500294, requestSize = 4415x2943, targetSize = 1080x720

Camera App 创建的 Surface 为 1080×720

07-15 03:33:47.328 I CamAp_CaptureSurface: [updatePictureInfo] width = 1080,height = 720,format = 1212500294,maxImage = 5, hasImageReader = false mCaptureType = heif

HAL 收到的 HEIF stream 同样是 1080×720

07-15 03:33:47.547 I mtkcam_hal_aidl_device: [configureStreams] Stream{width: 1080, height: 720, format: IMPLEMENTATION_DEFINED, usage: VIDEO_ENCODER, dataSpace: HEIF}

C2 HEIF Encoder 最终也按该尺寸配置:

CCodecConfig: c2::u32 raw.size.height = 720
CCodecConfig: c2::u32 raw.size.width = 1080

2. HEIF 流程确认

设备查询以下属性均为空:

adb shell getprop vendor.mtk.camera.app.heif.flow
adb shell getprop ro.vendor.mtk_heif_capture_support
adb shell getprop vendor.mtkcamapp.heif.mode

属性为空表示代码采用默认值,不代表 HEIF 未启用。日志明确确认当前走 AOSP HEIF flow:

CamAp_FormatCaptureRequestConfig: [setCameraCharacteristics] HEIF_AOSP_FLOW supportedFormats = [jpeg, heif]

因此空属性不是根因。

3. 有效信号与噪声

类型日志/现象判断
有效信号ignore odd HEIC size第一有效异常,直接指向非法尺寸
有效信号replace unsupported ... with 1080x720直接解释成片为何降为 0.8M
有效信号requestSizetargetSize 不一致证明降级发生在 Camera App 配置阶段
有效信号HAL configureStreams 1080x720证明 HAL 只是执行已降级目标
次要噪声VideoCapabilities: Unsupported mime image/vnd.android.heic后续 Encoder 创建成功,不是根因
次要噪声Media Quality Service not found不影响尺寸选择和 Encoder 创建
无关噪声Bluetooth VINTF、LBS service 报错与相机链路无关

三、原理分析(Root Cause Analysis)

1. 完整问题链路

S5K3M5SX static metadata 声明 13M 3:2 = 4415×2943

Camera App 读取 requestSize = 4415×2943

AOSP HEIF 检查发现宽高均为奇数

App 寻找相同 3:2 比例的合法 HEIC 尺寸

选择 1080×720

创建 1080×720 HEIF Surface

Camera HAL 与 C2 Encoder 正常按 1080×720 工作

照片旋转后显示 720×1080,约 0.8M

2. 根因

根因文件:

U:\mt8391_v16\mt8391_u\vendor\mediatek\proprietary\custom\mt8189\hal\imgsensor_metadata\s5k3m5sx_mipi_raw\config_static_metadata_project.h

该文件同时在 BLOB 和 YCbCr_420_888 中声明:

4415 × 2943

44152943 都是奇数。YUV420 色度采样要求至少偶数尺寸,平台 C2 HEIF Encoder 还声明了 16×16 对齐。因此该尺寸虽然进入 Camera characteristics 支持列表,却不能作为合法 HEIF 编码目标。

3. 为什么回退到 1080×720

App 会在合法 HEIC 尺寸中寻找与原设置相同的 3:2 比例。原本唯一接近 13M 的 3:2 尺寸因奇数被排除,合法候选中剩下 1080×720

支持列表虽然存在 4096×3072,但它是 4:3,不满足原设置的 3:2 比例,因此没有被选作替代值。

4. 各层责任判断

层级状态结论
Camera 设置 UI显示 metadata 声明的尺寸输入能力来自错误 metadata
Camera App HEIF 检查拒绝奇数尺寸并降级保护逻辑正确,不应删除
Camera HAL接收并配置 1080×720正常执行,不是根因
C2 HEIF Encoder成功按 1080×720 编码正常执行,不是根因
Sensor metadata声明奇数 BLOB/YUV 尺寸根因层级

四、排查路径(Debug Path)

步骤 1:逐层比较尺寸

目的: 判断尺寸在哪一层第一次发生变化。

adb logcat -c
# 设置问题尺寸、切换 HEIF 并复现
adb logcat -d -v threadtime |
  Select-String "updatePictureSize|setPictureSize|updatePictureInfo|configureStreams|HeifEncoder|CCodec"

判断:

  • 设置值错误:查 UI、DataStore、默认值。
  • requestSize 正确但 targetSize 变小:查 App capability/filter/fallback。
  • App 正确但 HAL stream 变小:查 Framework/HAL negotiation。
  • HAL 正确但 Encoder 变小:查 Codec。
  • 全链路尺寸正确但图库显示小:查 HEIF primary image、thumbnail 和 rotation。

本案例属于第二种。

步骤 2:找第一有效异常

优先搜索:

odd|unsupported|replace|HEIC size|requestSize|targetSize

本案例第一现场是:

ignore odd HEIC size = 4415x2943

后面的 HAL 和 Encoder 1080×720 都是结果。

步骤 3:确认 HEIF flow

adb shell getprop vendor.mtk.camera.app.heif.flow
adb shell getprop ro.vendor.mtk_heif_capture_support
adb shell getprop vendor.mtkcamapp.heif.mode

property 为空时必须结合源码默认值和运行日志,不能直接判断功能关闭。

步骤 4:用精确尺寸反查 metadata

rg -n "4415|2943" U:\mt8391_v16\mt8391_u\vendor\mediatek\proprietary\custom

检查同一尺寸在以下格式中的声明:

  • HAL_PIXEL_FORMAT_BLOB
  • HAL_PIXEL_FORMAT_YCbCr_420_888
  • 必要时检查 RAW、HEIC 和 duration 表

步骤 5:检查编码约束

核对:

  • 宽高是否为偶数;
  • 是否满足 2/16/32 对齐;
  • 是否超过 Codec max size;
  • 是否与 Sensor/ISP 输出能力一致。

步骤 6:刷机后清除旧设置

adb shell pm clear com.mediatek.camera

重新选择尺寸后,确认 requestSizetargetSizeupdatePictureInfoconfigureStreams 四个阶段一致。

五、解决方案(Solution)

1. 修改文件

U:\mt8391_v16\mt8391_u\vendor\mediatek\proprietary\custom\mt8189\hal\imgsensor_metadata\s5k3m5sx_mipi_raw\config_static_metadata_project.h

2. 修改点一:BLOB/JPEG 13M 3:2

修改前:

CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_BLOB, MINT64) //13mp 3:2
CONFIG_ENTRY_VALUE(4415, MINT64)        // width
CONFIG_ENTRY_VALUE(2943, MINT64)        // height

修改后:

CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_BLOB, MINT64) //13mp 3:2
CONFIG_ENTRY_VALUE(4416, MINT64)        // width
CONFIG_ENTRY_VALUE(2944, MINT64)        // height

3. 修改点二:YUV/HEIF 13M 3:2

修改前:

CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_YCbCr_420_888, MINT64) //13mp 3:2
CONFIG_ENTRY_VALUE(4415, MINT64)        // width
CONFIG_ENTRY_VALUE(2943, MINT64)        // height

修改后:

CONFIG_ENTRY_VALUE(HAL_PIXEL_FORMAT_YCbCr_420_888, MINT64) //13mp 3:2
CONFIG_ENTRY_VALUE(4416, MINT64)        // width
CONFIG_ENTRY_VALUE(2944, MINT64)        // height

4. 修复正确性

  • 44162944 都能被 16 整除。
  • 保持约 13MP 和接近 3:2 的产品定义。
  • BLOB 与 YUV 同步修改,避免跨格式能力不一致。
  • 保留 App 的奇数尺寸保护。
  • 原设计已经声明 4415 的放大输出,本次仅将其调整到合法对齐值。
  • 修改后已完成编译、刷机和实机拍照验证,功能通过。

建议验收日志满足:

support HEIC size = 4416x2944
requestSize = 4416x2944, targetSize = 4416x2944
updatePictureInfo width = 4416,height = 2944
configureStreams width = 4416,height = 2944

六、试错记录(Trial & Error)

1. 只看 HEIF property 为空

容易误判为 HEIF 没有配置。实际代码采用默认值,日志也确认 HEIF_AOSP_FLOW 正常启用。

经验: property 必须结合源码默认值和运行日志判断。

2. 只在产品名 custom 目录找配置

最初容易只检查:

vendor\mediatek\proprietary\custom\Kamvas_Pad_12_ROW

实际分辨率位于平台 Sensor metadata:

custom\mt8189\hal\imgsensor_metadata\s5k3m5sx_mipi_raw

经验: 相机能力通常按 platform + sensor 组织,不一定放在 product-name 目录。

3. 怀疑图库读取了缩略图

日志证明 App 在创建输出 Surface 前就已经降为 1080×720,HAL 和 Encoder 只是执行结果。

经验: 按“设置值 → Surface → HAL stream → Encoder → 文件”逐层比较。

4. 删除 Camera App 的奇数尺寸保护

这是错误方向。删除保护可能让非法 YUV/HEIF buffer 进入 HAL/Codec,引发配置失败、stride 错误、花图或编码失败。

经验: 保护逻辑暴露上游声明错误时,应修 metadata,不应绕过保护。

5. 修改 Codec XML

本问题不是 Codec 最大尺寸不足,而是宽高为奇数。Encoder 已成功创建,Codec XML 不是根因。

6. 只修改 BLOB 或只修改 YUV

HEIF 兼容尺寸可能由多种 stream format 共同决定。只改一组会继续造成能力不一致。

经验: 修改 stream configuration 时应检查同一尺寸在所有相关 pixel format 下的声明。

七、知识沉淀(Knowledge)

1. 菜单尺寸不等于最终编码尺寸

用户选择的逻辑值仍要经过:

  1. App 输出格式检查;
  2. ImageReader/Encoder Surface 创建;
  3. Camera HAL stream 配置;
  4. ISP 输出;
  5. JPEG/HEIF 编码;
  6. 文件方向与 metadata 写入。

任意阶段都可能拒绝或回退尺寸。

2. HEIF 比 JPEG 更依赖对齐

JPEG/BLOB 对部分尺寸可能表现得更宽松,但 HEIF 常通过 YUV420、Surface 和 HEVC/HEIC Encoder 完成。YUV420 要求偶数采样,硬件 Codec 还可能要求 16、32 或更高粒度对齐。

因此“JPEG 能拍”不能证明相同尺寸一定能用于 HEIF。

3. 能力声明必须跨层一致

Sensor/ISP 可输出
    ∩ HAL metadata 已声明
    ∩ Camera App 会选择
    ∩ Buffer format/stride 合法
    ∩ Codec 支持范围与对齐条件

任何一层不一致,都可能出现菜单可选但实际回退、configureStreams 失败或编码异常。

4. 优先找第一次改变尺寸的位置

最终看到的是 720×1080,但第一现场是:

ignore odd HEIC size = 4415x2943

调试时应优先找第一次改变尺寸、第一次返回失败或第一次触发 fallback 的位置。

5. 修改能力后注意 App 缓存

Camera App 会保存照片大小。metadata 更新后,旧值仍可能被读取,因此刷机后应清除相机数据或实现旧值迁移。

八、复用模板(Reusable Pattern)

1. 相机成片尺寸不一致检查表

  • 确认问题发生在 JPEG、HEIF、RAW 中的哪种格式。
  • 记录 UI 选择的比例和精确分辨率,不只记录“M”数。
  • 搜索 updatePictureSize,确认 App 保存值。
  • 比较 requestSizetargetSize
  • 搜索 updatePictureInfo,确认 Surface 尺寸。
  • 搜索 configureStreams,确认 HAL 收到的尺寸。
  • 搜索 CCodecConfig raw.size,确认编码尺寸。
  • 检查最终文件主图、旋转方向和 thumbnail。
  • 反查对应 Sensor metadata 的 BLOB、YUV、RAW、HEIC 声明。
  • 检查宽高奇偶、对齐和 Codec 最大尺寸。
  • 同步修改相关 pixel format。
  • 刷机后清除 Camera App 旧设置再验证。

2. 推荐日志关键词

PictureSize|updatePictureSize|setPictureSize|requestSize|targetSize
HEIC size|odd|unsupported|replace|updatePictureInfo
configureStreams|HeifEncoder|HeifWriter|CCodecConfig|onPictureCallback

3. 通用判断分支

观察结果优先检查方向
设置值本身错误Camera UI、DataStore、默认值、restriction
request 正确但 target 改变App capability/filter/fallback
App target 正确但 HAL stream 改变Framework/HAL stream negotiation
HAL 正确但 Encoder 改变MediaCodec/C2/OMX
编码尺寸正确但图库显示错误HEIF container、primary image、thumbnail、rotation
只在特定 Sensor 发生对应 imgsensor_metadata/<sensor>

九、最终文档(Markdown 格式)

闭环结论

项目结论
可见现象HEIF 13M 3:2 成片降为 720×1080
第一有效异常ignore odd HEIC size = 4415x2943
直接原因App 将非法奇数尺寸回退到 1080×720
根本原因S5K3M5SX metadata 在 BLOB 和 YUV 中错误声明 4415×2943
修复方案两组尺寸同步修改为满足 16 对齐的 4416×2944
无需修改HEIF property、Codec XML、App 奇数尺寸保护
验证结果编译刷机并实机验证通过,成片分辨率恢复正常
闭环状态已解决

一句话经验

遇到相机设置尺寸与成片尺寸不一致时,应按“App 设置值 → 目标 Surface → HAL stream → Encoder”逐层比对,并优先修复不满足格式对齐条件的上游能力声明。