The fp has two unrelated ways to make a frame smaller before it reaches the card, and six names for where to tap the result. Most of those names are never used. This is what each one is, which the camera actually switches on, and the decision that picks between them.
Three things, if you read nothing else:
Crmf and Hbin2 are the only ones the firmware ever
switches on. Gain, Vbin and Spc are never
written at all, and Hbin — the one everybody assumed was the
normal case — is only ever written to a tap that is left switched off.
The hardware has two horizontal shrink stages and only one vertical. That is exactly why the list reads Vbin, Hbin, Hbin2. They are positions on a chain, not different maths.
When the resampler is on, the binning is not switched off — it is moved to the second stage. And in the one case that matters for recording, it is not even moved: both run at once.
Raw pixels from the sensor do not go straight to a file. They run down a correction chain — gain, defect correction, various raw-domain fixes — and the firmware can pull a copy out of that chain at several points and write it to memory. Those pull-out points are called windows, and there are three of them.
Why three? Because recording and the live-view screen usually want different sizes. One window can feed the file while another feeds the display.
The six names come from a debug line the firmware prints when it
sets this up (crct1_win_a0 : CrctHbinToBufA and so on). That line is
where all four names in this page's title come from, and reading it as a list of
alternatives is what sent the earlier notes wrong — three of the six are
positions nothing ever selects.
Binning and resampling are not two settings of one thing. They are separate hardware doing separate jobs.
| hbin / vbin | RWZM | |
|---|---|---|
| what it does | weighted average of 3 or 5 neighbouring same-colour pixels | general resampler, any ratio |
| ratios available | horizontal ÷3 or ÷5, vertical ÷3 only | anything from 1.0× up, in 1/1024 steps |
| where | a stage on the correction chain | a separate path beside the chain |
| how it is set | an enum: 0, 1, 2 | a number: 1024 means 1.0× |
The binning enum is tiny and the conversion is worth seeing, because it explains a gap people keep tripping over:
| enum | horizontal taps | vertical taps |
|---|---|---|
| 0 | 1 — off | 1 — off |
| 1 | 3 — ÷3 | 3 — ÷3 |
| 2 | 5 — ÷5 | illegal |
The resampler's number is a divisor scaled by 1024, so it reads directly as a shrink factor:
if (1024 >= ratio) ratio = 1024. There is no
upper check anywhere in the path — 3072 is simply the largest the stock tables
use.Here is the part that answers "what is Hbin2". Laying the registers out by what they drive:
Vbin, two Hbin. They are
positions on a chain, not different algorithms. The sub-pipeline, used for
live view, is a cut-down copy with no second horizontal stage at all.Because of an arbitration rule. When the resampler is active, the firmware sometimes has to take the horizontal binning out of stage 1 — but it does not throw the setting away. Four instructions, and they are worth reading literally:
All of the above is settings. What actually picks them is a single function that looks at two things — how much does recording want to shrink and how much does live view want to shrink — and falls into one of six outcomes.
This function was previously believed to be unreachable without a camera, on the grounds that the table holding it was built at runtime. It is not: the table is a constant in ROM and the decision is eight plain branches.
Pick what recording and live view each ask for and see which branch the firmware falls into. The three preset buttons are the cases that were independently traced in an emulator, and this page agrees with all three.
Running the recovered decision over every profile in the firmware gives the whole picture at once. This is the answer to "which of the six names matter":
| selector | name | written by the firmware? | ever on a window that is enabled? |
|---|---|---|---|
| 0 | CrctGainToBufA | never | no |
| 1 | CrctCrmfToBufA | yes | yes — 253 profiles |
| 2 | CrctVbinToBufA | never | no |
| 3 | CrctHbinToBufA | yes, in branch E | no — window is off |
| 4 | CrctHbin2ToBufA | yes | yes — 36 profiles |
| 5 | CrctSpcToBufA | never | no |
Two of six. Hbin is written in exactly one branch, onto a window
that branch leaves switched off — so the tap everyone assumed was the normal
horizontal case is the one that never carries anything.
There is a second, separate copy of this decision belonging to
another imager object in the firmware. It was checked too, and it is narrower still:
its selectors are only ever Crmf or Hbin2. What selects
between the two imagers has not been traced.
Branch E — recording wants to shrink, live view does not — is the one that matters for every UHD clip the camera has ever shot. It does something the earlier notes said was impossible.
The arbitration from the earlier diagram is guarded by a flag. In branch E the
firmware sets that flag to 1, which makes the arbitration condition
false, so the move never happens. And the main pipeline is handed recording's
resampler ratio together with live view's binning taps:
The weights are not hard-wired in silicon; they come from one of two 56-byte records in ROM, and branch E picks the second. They are strikingly different:
A real average. Used by the DC Crop path.
Centre carries 87.5%. Close to a straight pass-through.
That matters for image quality: the mode that matters most for recording is using the kernel that barely averages at all. Independent noise analysis of real clips found the same thing from the other direction — 3K footage shows almost no correlation between neighbouring same-colour pixels, where UHD shows clearly more.
Three questions that come up whenever someone wants anamorphic or a different aspect ratio out of this hardware.
In the code, yes, with no restriction at all. Horizontal and vertical are two separate registers, clamped separately by two structurally identical pieces of code, and the enable test is an or: the resampler switches on if either axis is not 1.0×. If the hardware required a square ratio, that test would be the place to enforce it, and it does not.
But no stock profile does it. Across all 306, the live-view pair and the recording pair each have horizontal equal to vertical, row for row. There is no factory precedent to copy, and no reference footage to compare against.
No. The clamp is one-sided. The value is a divisor, so enlargement needs something below 1024, and anything at or below 1024 is pulled back to 1024. The only way past that is writing the hardware register directly, and whether the silicon does anything sensible below 1.0× is simply unknown — there is no evidence either way in the code.
The resampler is the only layer that can, which is worth stating plainly:
| layer | ratios it can produce |
|---|---|
| sensor readout mode | a fixed menu of geometries |
| hbin / vbin | ÷3 or ÷5 horizontally, ÷3 vertically |
| RWZM | anything, and the axes are independent |
Three things have to be handled if anyone tries it. The output-size formula runs once per axis, so the size the firmware computes changes with the ratio, and that size has to line up with what the producer actually writes, the canvas, and the preview descriptor. The four ratio fields cannot be split — setting only the recording pair and leaving the preview pair alone has been tried on a camera and produced a corrupted recording followed by a lockup. And there is no factory example, so there is nothing to compare a result against.
If someone does try it, branch C is the least entangled starting point: one pipeline, one set of numbers. Branch E is the worst, because there the binning and the resampler are stacked on the same pipeline and an anamorphic ratio would pass through both.
This page exists because three load-bearing claims in the project's own research notes turned out to be wrong. They are listed here rather than quietly fixed, because each one had already shaped work.
A fourth one was mine, during this work. A first pass at the profile table concluded that a third of the stock profiles used unequal horizontal and vertical ratios. That was wrong: the table's columns are not laid out in the order of the structure they describe, and reading neighbouring columns as neighbouring fields turned "preview versus recording" into "horizontal versus vertical". The correct answer is that no stock profile is anamorphic. The error was caught by checking four known addresses against an independent description of the table.
Crmf and Spc actually correct. Spc
is now the lowest priority of the two, since nothing can select it.kind input, and why one particular value makes the decision
use the a7 window instead of a0.Everything here comes from the Ver.5.02 firmware image. The branch that decides the path, the arbitration, the register writers and the enum conversions were each read as instructions rather than trusted from a decompiler. Three independent confirmations were available and all three agree: an emulator trace of the same firmware from the FP3K technical handoff covering three configurations, that handoff's separate description of the profile table, and the noise analysis of real clips which matches the kernel that branch E selects.
The working notes behind this page are in the repository, and
several are in Traditional Chinese:
research/imaging-hw/notes/CRCT_PATH_SELECTOR_SOLVED.md is the primary
one, with CRCT_REDUCTION_PATHS.md and
REDUCTION_INVENTORY.md as the earlier passes it corrects.