Environment
Raspberry Pi 4 Model B, Raspberry Pi HQ Camera (IMX477), vc4 pipeline
Linux raspberry 6.18.46-v8+ #1999 SMP PREEMPT Mon Aug 24 15:30:47 BST 2026 aarch64
libcamera v0.7.2+rpt20260817
rpicam-apps v1.13.0 07-08-2026
Summary
The IMX477 cam helper parses the sensor die temperature from embedded data correctly — it appears in the IPARPI debug output on every frame. However, controls::SensorTemperature is absent from the metadata of a still capture, while ExposureTime, AnalogueGain and FrameDuration — set from the same DeviceStatus in ipa_base.cpp — are present.
This matters for astrophotography, which is the use case the SensorTemperature control was introduced for: dark frame and bad pixel map calibration needs the sensor temperature recorded per captured frame.
Steps to reproduce
LIBCAMERA_LOG_LEVELS=IPARPI:DEBUG rpicam-still --nopreview --immediate --raw
--gain 8 --shutter 1000000 --metadata /tmp/e3.json --metadata-format json
-o /tmp/e3.jpg 2>&1 | grep -E "Metadata updated" | tail -3
python3 -m json.tool /tmp/e3.json
Debug output — temperature is parsed:
[2:06:25.576433965] [2350] DEBUG IPARPI cam_helper.cpp:249 Metadata updated - Exposure time: 999982.88us Frame length: 36208 Line length: 27.63us Gain: 8 Temperature: 50
[2:06:27.577753265] [2350] DEBUG IPARPI cam_helper.cpp:249 Metadata updated - Exposure time: 999982.88us Frame length: 36208 Line length: 27.63us Gain: 8 Temperature: 50
[2:06:29.578850741] [2350] DEBUG IPARPI cam_helper.cpp:249 Metadata updated - Exposure time: 999982.88us Frame length: 36208 Line length: 27.63us Gain: 8 Temperature: 50
Still capture metadata — SensorTemperature absent:
{
"ExposureTime": 999982,
"ColourGains": [
1.866805,
3.518852
],
"AnalogueGain": 8.0,
"FrameDuration": 1000590,
"Lux": 4.869115,
"SensorTemperature": 50.0,
"AeState": 0,
"ColourTemperature": 2435,
"SensorBlackLevels": [
4096,
4096,
4096,
4096
],
"FocusFoM": 10085,
"ColourCorrectionMatrix": [
1.974859,
-0.71568,
-0.25919,
-0.434733,
2.098793,
-0.66406,
-0.049174,
-0.844107,
1.893281
],
"DigitalGain": 1.000017,
"ControlListSequence": 1,
"ScalerCrop": "(0, 0)/4056x3040",
"FrameWallClock": 1788631100703833088,
"SensorTimestamp": 7589493422000
}
Cross-check: the sensor really does report a valid temperature
Reading register 0x013a directly over I²C while the sensor is streaming:
$ rpicam-hello --nopreview -t 10000 >/dev/null 2>&1 &
$ sleep 3
$ sudo i2ctransfer -f -y 10 w2@0x1a 0x01 0x3a r1
0x34
0x34 = 52, matching Temperature: 52 in the IPA debug output exactly.
Embedded data path looks healthy
$ media-ctl -p -d /dev/media2
- entity 1: imx477 10-001a (2 pads, 2 links, 0 routes)
pad1: SOURCE
[stream:0 fmt:unknown/16384x1 field:none ...]
-> "unicam-embedded":0 [ENABLED,IMMUTABLE]
Embedded buffers are queued and dequeued normally (RPI:DEBUG):
DEBUG RPI vc4.cpp:814 Stream Unicam Embedded buffer dequeue, buffer id 1, ...
DEBUG RPI vc4.cpp:1010 Signalling prepareIsp: Embedded buffer id: 1
Side note: media-ctl prints the metadata pad's mbus code as unknown on this kernel. That may be unrelated, but I mention it in case the metadata mbus format codes changed in 6.18.
Analysis
In ipa_base.cpp all four values come from one block:
cpp
DeviceStatus *deviceStatus = rpiMetadata.getLocked("device.status");
if (deviceStatus) {
libcameraMetadata_.set(controls::ExposureTime, ...);
libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogueGain);
libcameraMetadata_.set(controls::FrameDuration, ...);
if (deviceStatus->sensorTemperature)
libcameraMetadata_.set(controls::SensorTemperature, *deviceStatus->sensorTemperature);
Since the first three are present and the fourth is not, deviceStatus->sensorTemperature must be empty for the frame that is reported. That would be the case if the still frame's DeviceStatus came from DelayedControls and CamHelperImx477::prepare() never updated it from embedded data for that frame.
A possible trigger appears in the log around the mode switch to the still configuration:
DEBUG RPI vc4.cpp:1034 Dropping unmatched input frame in stream Unicam Embedded
DEBUG RPI vc4.cpp:1034 Dropping unmatched input frame in stream Unicam Embedded
DEBUG RPI vc4.cpp:1053 Waiting for next embedded buffer.
I have not verified that this is the cause — that is speculation on my part; the reproducible facts are the three sections above.
Expected behaviour
SensorTemperature should be present in still capture metadata whenever it is available in the preview stream, so applications can record it per captured frame.
Environment
Raspberry Pi 4 Model B, Raspberry Pi HQ Camera (IMX477), vc4 pipeline
Linux raspberry 6.18.46-v8+ #1999 SMP PREEMPT Mon Aug 24 15:30:47 BST 2026 aarch64
libcamera v0.7.2+rpt20260817
rpicam-apps v1.13.0 07-08-2026
Summary
The IMX477 cam helper parses the sensor die temperature from embedded data correctly — it appears in the IPARPI debug output on every frame. However, controls::SensorTemperature is absent from the metadata of a still capture, while ExposureTime, AnalogueGain and FrameDuration — set from the same DeviceStatus in ipa_base.cpp — are present.
This matters for astrophotography, which is the use case the SensorTemperature control was introduced for: dark frame and bad pixel map calibration needs the sensor temperature recorded per captured frame.
Steps to reproduce
LIBCAMERA_LOG_LEVELS=IPARPI:DEBUG rpicam-still --nopreview --immediate --raw
--gain 8 --shutter 1000000 --metadata /tmp/e3.json --metadata-format json
-o /tmp/e3.jpg 2>&1 | grep -E "Metadata updated" | tail -3
python3 -m json.tool /tmp/e3.json
Debug output — temperature is parsed:
[2:06:25.576433965] [2350] DEBUG IPARPI cam_helper.cpp:249 Metadata updated - Exposure time: 999982.88us Frame length: 36208 Line length: 27.63us Gain: 8 Temperature: 50
[2:06:27.577753265] [2350] DEBUG IPARPI cam_helper.cpp:249 Metadata updated - Exposure time: 999982.88us Frame length: 36208 Line length: 27.63us Gain: 8 Temperature: 50
[2:06:29.578850741] [2350] DEBUG IPARPI cam_helper.cpp:249 Metadata updated - Exposure time: 999982.88us Frame length: 36208 Line length: 27.63us Gain: 8 Temperature: 50
Still capture metadata — SensorTemperature absent:
{
"ExposureTime": 999982,
"ColourGains": [
1.866805,
3.518852
],
"AnalogueGain": 8.0,
"FrameDuration": 1000590,
"Lux": 4.869115,
"SensorTemperature": 50.0,
"AeState": 0,
"ColourTemperature": 2435,
"SensorBlackLevels": [
4096,
4096,
4096,
4096
],
"FocusFoM": 10085,
"ColourCorrectionMatrix": [
1.974859,
-0.71568,
-0.25919,
-0.434733,
2.098793,
-0.66406,
-0.049174,
-0.844107,
1.893281
],
"DigitalGain": 1.000017,
"ControlListSequence": 1,
"ScalerCrop": "(0, 0)/4056x3040",
"FrameWallClock": 1788631100703833088,
"SensorTimestamp": 7589493422000
}
Cross-check: the sensor really does report a valid temperature
Reading register 0x013a directly over I²C while the sensor is streaming:
$ rpicam-hello --nopreview -t 10000 >/dev/null 2>&1 &
$ sleep 3
$ sudo i2ctransfer -f -y 10 w2@0x1a 0x01 0x3a r1
0x34
0x34 = 52, matching Temperature: 52 in the IPA debug output exactly.
Embedded data path looks healthy
$ media-ctl -p -d /dev/media2
pad1: SOURCE
[stream:0 fmt:unknown/16384x1 field:none ...]
-> "unicam-embedded":0 [ENABLED,IMMUTABLE]
Embedded buffers are queued and dequeued normally (RPI:DEBUG):
DEBUG RPI vc4.cpp:814 Stream Unicam Embedded buffer dequeue, buffer id 1, ...
DEBUG RPI vc4.cpp:1010 Signalling prepareIsp: Embedded buffer id: 1
Side note: media-ctl prints the metadata pad's mbus code as unknown on this kernel. That may be unrelated, but I mention it in case the metadata mbus format codes changed in 6.18.
Analysis
In ipa_base.cpp all four values come from one block:
cpp
DeviceStatus *deviceStatus = rpiMetadata.getLocked("device.status");
if (deviceStatus) {
libcameraMetadata_.set(controls::ExposureTime, ...);
libcameraMetadata_.set(controls::AnalogueGain, deviceStatus->analogueGain);
libcameraMetadata_.set(controls::FrameDuration, ...);
if (deviceStatus->sensorTemperature)
libcameraMetadata_.set(controls::SensorTemperature, *deviceStatus->sensorTemperature);
Since the first three are present and the fourth is not, deviceStatus->sensorTemperature must be empty for the frame that is reported. That would be the case if the still frame's DeviceStatus came from DelayedControls and CamHelperImx477::prepare() never updated it from embedded data for that frame.
A possible trigger appears in the log around the mode switch to the still configuration:
DEBUG RPI vc4.cpp:1034 Dropping unmatched input frame in stream Unicam Embedded
DEBUG RPI vc4.cpp:1034 Dropping unmatched input frame in stream Unicam Embedded
DEBUG RPI vc4.cpp:1053 Waiting for next embedded buffer.
I have not verified that this is the cause — that is speculation on my part; the reproducible facts are the three sections above.
Expected behaviour
SensorTemperature should be present in still capture metadata whenever it is available in the preview stream, so applications can record it per captured frame.