Repository navigation
Automatic video standard
src/video_standard_search.cpp (UpdateVideoStandard, VerifyStandardColour, StartSignalWatch),
src/capture/dshow_util.cpp (AutoStandardCandidates,
VideoStandardColourCandidates, VideoStandardColourSystem)
An analogue decoder has to be told which standard it is looking at. Set it wrong and you get either no picture at all or a picture decoded by the wrong rules. On Automatic, qBlank works it out and keeps working it out: switching a console between 50 and 60 Hz, or unplugging the cable and putting it back, is followed without touching the settings.
The setting is one long in the profile:
| Value | Meaning |
|---|---|
0 |
Leave alone — never call put_TVFormat
|
-1 |
Automatic |
| anything else | That standard, set once when the graph starts |
The decoder answers exactly one question — get_HorizontalLocked, "am I locked?"
— and that question is about line frequency, not about colour. Several standards
lock equally well on the same line count:
| Lines | Standards that all lock |
|---|---|
| 625 | PAL B, PAL N, SECAM B |
| 525 | PAL 60, NTSC M, PAL M, NTSC 4.43 |
The decoder reports a lock for the wrong one just as confidently as for the right one, and a wrong choice inside a line count is not a blank screen — it is a picture with wrong colour. Measured on 30.08.2026, one PAL scene decoded three ways:
| Standard | Colour | Dark regions |
|---|---|---|
| PAL B (correct) | 0.152 | 0.101 |
| SECAM B (wrong) | 0.461 | 0.353 |
| PAL N (wrong) | 0.017 | 0.014 |
SECAM-decoding a PAL signal does not produce a grey picture; it produces a strongly tinted one — on screen, a bright red background where black should be. So "has colour" alone is not the test, and the second stage exists.
StartSignalWatch() spawns a thread that reads the current standard and the
lock flag together, ten times a second, and publishes them with a sequence
counter. Both come from the same pass deliberately: asked separately they could
come from different moments, and that is exactly how a display ends up reporting
one standard as locked while another is set on the card.
The thread holds its own ComPtr to the filter, so tearing the graph down
cannot pull the object out from under it.
The poll rate is the floor under every deadline on this page. Before judging
a freshly set standard, UpdateVideoStandard waits for two fresh readings,
so what is judged is the standard that is actually set rather than the one
before it. At the old 250 ms cadence that was 0.25–0.5 s of pure waiting inside
every measurement; at 100 ms it is 0.1–0.2 s.
UpdateVideoStandard() runs on the main loop:
- Does nothing unless the profile says
-1and the capture is running. - Locked → settled. If a candidate was being tried, the line count may have changed with it, so the graph is rebuilt around the new format, the crop is reset (see below), the colour measurement is restarted, and stage two runs.
-
Not locked → after
kStandardLostSeconds(1.5 s), step to the next candidate. - After a full pass with nothing locking, back off for
kStandardBackoffSeconds(6 s) — the console is probably off — and park the card on the first candidate rather than on whatever the pass ended with.
That last point was a real bug. The candidate list ends with the rarest standards, so a pass left NTSC 4.43 on the card; because the lock is horizontal only, NTSC 4.43 then confirms itself against any 525/60 source. A PAL-60 GameCube switched on during the pause was reliably detected as NTSC 4.43 — and that is the most common sequence of all, qBlank first and the console second.
AutoStandardCandidates() returns one candidate per line count and colour
system, ordered by the configured region, not one per table entry. Trying PAL B
and then PAL G would be asking the same question twice — they differ in the
sound carrier, which is no part of the picture.
The standard that was last good and its 50/60 Hz partner are moved to the
front and given kStandardPreferredSeconds (2 s) instead of the ordinary
window. A console that is restarting or changing mode needs a moment before
anything stable comes out of it.
Only on an analogue input. A card with both kinds of input still reports its analogue standards while it sits on HDMI, and until 5.2.1 the search ran there too. It found nothing and left the analogue decoder on NTSC M. Now an input set to Digital, or one the card reports as digital, gets no search at all.
kStandardSettleSeconds is what an ordinary candidate gets to show a lock.
It is set from measurement, and the measurement is in the log — every success
writes Videonorm automatisch gefunden: … (Lock nach %.2f s).
| Lock times measured | |
|---|---|
| At 250 ms polling, ten values over three sessions | 0.32 – 0.88 s |
| At 100 ms polling, after a lost lock (31.08., 03:09) | 0.73 s |
| At 100 ms polling, from a forced wrong standard (31.08., 05:24 and 05:27) | 0.24 s, 0.26 s |
The deadline is 1.25 s. It was briefly 1.0 s, derived from the argument that removing 0.3 s of polling wait should move the worst case from 0.88 s to about 0.6 s. The first measurement with the new cadence came back at 0.73 s and did not support that, so the deadline was set from the measurement instead: with up to 0.2 s of polling wait, the worst case of that kind is around 0.83 s, and 1.25 s stands to it as 1.5 s stood to 0.88 s.
If those log values start approaching 1.25 s, the deadline belongs back at 1.5.
That deadline covers every lock ever measured here, including one from a source that is still booting. For the candidate that turns out to be the answer, that is right. For the other seven it is waste: a standard with the wrong line count never locks at all — it only sits out the deadline. Eight candidates at 1.25 s is ten seconds, of which nine go to standards that were disproved in their first tenth of a second.
So the list is walked twice. The first pass gives every candidate
kStandardFastSeconds (0.8 s, 0.6 s before 5.2.1) and accepts that it may
miss a slow lock; if it finds nothing, the second pass walks the same list with
the full deadline. Nothing is ever discarded for good — what the fast pass
leaves behind, the patient one picks up — and the worst case grows only by the
length of the fast pass, 6.4 s.
The 0.6 s comes out of the same series of measurements as the deadline above. Six real locks:
| Source | Lock |
|---|---|
| Freshly switched on, still booting | 0.78 / 0.72 / 0.76 s |
| Signal already present | 0.30 / 0.39 / 0.55 s |
| After a lost lock | 0.73 s |
The line between those two groups is not an accident of the card. What makes the difference is whether the source itself is stable yet. 0.6 s sits above the slowest measurement on a present signal (0.55) and below the fastest on a booting one (0.72), which is exactly the right place: a source that is not delivering yet loses the fast pass regardless — at that moment the correct standard does not lock either, whether you give it 0.6 or 1.25 s — and it is caught by the second pass. What the fast pass is there to win is the commonest case of all, a running console switched between 50 and 60 Hz.
Why it is 0.8 s now. On 25.09 PAL B missed 0.6 s on a running Switch right after an input change, and SECAM B locked next. The patient pass would have caught PAL B, but it never came, because a lock ends the search. Two changes since 5.2.1:
- The fast pass gives 0.8 s.
- A lock proves the line count, not the standard. A standard earlier in the list with the same lines only failed the deadline. So after a lock qBlank sets the standard that comes first for that line count, and the colour check then says whether it is right.
Between the two passes there is no back-off and no parking. Both of those belong at the end of the search, not in its middle: the pause is the answer to "there is nothing here", and after a fast pass that is not yet established.
The log says which pass discarded what, and it says it for the first two rounds only — which are now precisely the fast one and the patient one:
Videonorm: PAL B nach 0.61 s ohne Lock verworfen (schneller Durchgang)
Videonorm: schneller Durchgang ohne Lock (4 Normen zu je 0.60 s), zweiter Durchgang mit 1.25 s
Their comparison is the check on the constant. A standard that fails the fast pass and locks in the patient one says 0.6 s is cut too fine; sources with a present signal landing regularly in the second pass say the same.
A standard with the wrong line count delivers no frames at all into a graph built for the old size. That is not evidence against it — the lock is read from the decoder and works without frames, and the standard that delivers nothing may well be the right one.
So starvation (kStandardStarvedSeconds, 2 s without a frame) is never used to
discard a candidate. It is used only to stop waiting on one: the extra
patience of the preferred places falls away, and the deadline is shortened
retroactively, on each tick, once starvation becomes provable.
That "retroactively" matters. The first version of this decided starvation once, at the moment the candidate was set — when nothing has yet been missing long enough to count — so it evaluated false and the full window was granted anyway. On 31.08. at 02:43:39 PAL B was given its whole preferred window although no frame had arrived for seven seconds.
VerifyStandardColour() measures the picture rather than asking the card.
Two numbers come out of the renderer: how much colour is present
(chromaEnergy) and how far dark areas are tinted (darkChromaEnergy).
The second is what catches SECAM-on-PAL, and it was missing at first — the "has
colour" test passed the misdecode, the misdecode counted as confirmed, and it
was never questioned again.
If the standard already set shows confident colour (≥ 0.080) and neutral darks (< 0.18), that is the answer and nothing is switched. This runs in normal operation, so most of the time the round never happens at all.
Doubt has two quite different causes, and only one of them is a question a round can answer. A lit picture with no colour means the carrier was wrong, and which one is right is exactly what the candidates settle among themselves. A black picture with no colour means it is black. Every candidate measures the same zero there, and no standard can be picked out of four identical numbers.
So before a round starts, the share of measured blocks that had any light in
them is checked (chromaLitFraction() — the same blocks, window and crop the two
colour numbers came from). Below a tenth, the round is postponed.
A tenth is far away from anything ordinary content produces. Measured on a running GameCube on 31.08. at 05:43, with the confidence threshold raised artificially so a round would be forced on a live picture: 54 % lit, five times the threshold. The case this exists for was on the other side of it, at 95 % of the picture below luma 16.
This was measured, not anticipated. On 31.08. at 05:30:03 a round ran on a GameCube screen that was black but for one bright element:
05:30:03.047 Wertebereich erkannt: ... 95.135 % unter 16
05:30:03.099 PAL 60 ist zweifelhaft (Farbe 0.005, dunkle Bereiche 0.002)
05:30:03.931 NTSC M gemessen -- Farbe 0.002
05:30:04.773 PAL M gemessen -- Farbe 0.003
05:30:05.604 NTSC 4.43 gemessen -- Farbe 0.003
05:30:06.438 PAL 60 gemessen -- Farbe 0.163 <- the picture came back
Two and a half seconds of visibly switching through three wrong standards for four times nothing. When the picture returned, one measurement settled it.
The existing dead-input guard does not catch this and should not: it asks
SignalVerdict::Flat, whether anything is arriving at all, and something was —
the luma spread was 154. "There is something to see" and "there is enough to see
to measure colour by" are two questions.
Two properties of the wait matter:
- Tinted darks go past it into the round, even on a dark picture. Colour sitting in the black is evidence of a wrong carrier, not a missing measurement, and a dark picture is where that evidence is clearest — those are the blocks it is measured on.
- Waiting spends nothing. No attempt is counted and no standard is marked checked, so a console that is black for the first seconds of its boot still has all three attempts left when its picture arrives. A round that never ran must not count as one that came back undecided.
The lit share is written into the line that opens a round, so a round that later measures a surprising row of zeroes has its explanation on the line above it.
Otherwise the remaining candidates for this line count are set in turn and each
is measured. VideoStandardColourCandidates() skips anything whose colour
signature — colour system plus subcarrier frequency — matches a candidate
already in the list. Nothing in the picture could tell those apart. At 525 lines
exactly one pair collides, NTSC M and NTSC M (Japan): both NTSC on 3.58 MHz,
differing only in the 7.5 IRE setup pedestal, which is a brightness property
this measurement does not look at. That drops the round from five candidates to
four. At 625 lines nothing collides.
Between candidates the card gets kColourSettleSeconds (0.10 s) for its chroma
PLL, and the measurement is reset at the end of that window rather than at
the start. Reset at the start and the switching moment is measured with the
candidate: reproduced on 30.08. by setting the window to zero, PAL N read 0.047
and 0.064 instead of 0.012 to 0.021, and SECAM B's darks read 0.246 instead of
0.271 to 0.410 — every candidate smeared towards its predecessor.
That deadline used to be 0.5 s and used to be the whole wait. It is now only the floor, because a deadline is the wrong instrument here — measured on 31.08., 0.15 s was plenty for three of the four 525-line standards and nowhere near enough for the fourth:
| Candidate | 0.5 s deadline | 0.15 s, three runs |
|---|---|---|
| NTSC M | 0.018 | 0.017 / 0.017 / 0.017 |
| PAL M | 0.023 | 0.023 / 0.023 / 0.024 |
| NTSC 4.43 | 0.065 | 0.065 / 0.065 / 0.065 |
| PAL 60, on the return | 0.119 | 0.000 / 0.047 / 0.095 |
Three standards identical to the thousandth, one broken — and broken upwards with the delay, reading 0.000, 0.047 and 0.095 at 0.276, 0.327 and 0.393 s after the switch. That is not scatter, it is a settling curve, and it has a reason: the PAL burst alternates phase line by line, and the ident that recovers it needs more lines than NTSC's fixed phase. Twice in three runs the round discarded itself over the result, because a return reading taken too early no longer matched the opening one and the scene-change guard fired.
A shared deadline therefore always pays for the slowest standard, and every
other candidate pays with it. But the decoder announces when it is ready: while
it is locking, the reading climbs; once locked, it stands. So the round asks
that instead. Each candidate is measured in windows of
kChromaFramesWantedDense (3) frames, and the first window that is not
higher than the one before it is the one that counts.
Directional, not merely similar, and that is the point: a moving picture wanders
in both directions and is done at its first window that did not rise, while a
locking decoder can only come from below. kColourStableGiveUpSeconds (1.2 s)
ends a candidate that never settles, takes its last reading as the best one
available, and says in the log that it did.
Fourteen rounds across three builds gave every number identical to the 0.5 s reference, with no rejected comparison. 0.33 s per standard, and 0.56 s for PAL 60 where it takes a third window — the one candidate that needs the time gets it, and only it pays.
A full round, forced on a live picture on 31.08. at 05:43. It took 3.3 s then; the same round takes 1.7 s since the change described above, with the same numbers:
| Candidate | Colour | Dark regions |
|---|---|---|
| PAL 60 (correct) | 0.192 | 0.107 |
| NTSC M | 0.029 | 0.025 |
| PAL M | 0.043 | 0.037 |
| NTSC 4.43 | 0.119 | 0.079 |
| PAL 60 again | 0.191 | 0.108 |
The winner has to be clearly ahead, not merely ahead: 1.6× when it has visible colour, 3.0× when both are faint, and nothing counts below a floor of 0.005, because a ratio needs a denominator. Where two candidates both have colour, the one with the cleaner darks wins.
In the round above that margin was met by a hair: 0.192 against NTSC 4.43's 0.119 is 1.61×, where 1.6 is required. That is not an accident of the scene, and it is not fixed by loosening the margin — those two standards share the same 4.43 MHz subcarrier, and neither colour amount nor darks can separate them at all. What separates them is measured directly, one section down.
There is deliberately no absolute threshold for "this black is tinted". Below the luma threshold there are also genuinely dark red and dark blue areas, which have colour by right, and how much of that is in frame depends on the scene — an absolute number measures the scene as much as the carrier. The comparison does not: all candidates see the same scene, so what separates them is the carrier alone. The first attempt at a fixed value, 0.060, promptly threw out the correct standard.
PAL 60 and NTSC 4.43 cannot be told apart by the two rules above, and the
reason is not a threshold that needs tuning. They carry colour on the same
4.43 MHz subcarrier. The only difference is that PAL reverses the V (R−Y)
phase on every other line and NTSC does not — and both chromaEnergy and
darkChromaEnergy average over blocks that span more than one line, which is
precisely where that reversal cancels itself out.
So the wrong standard measured less. An NTSC decoder on a PAL signal leaves the reversal in place, adjacent lines partly cancel, and the result is less colour overall and less colour in the darks. Which meant NTSC 4.43 kept winning "cleanest blacks" by decoding less. Nothing built on those two numbers can fix that; the sign is wrong, not the size.
VideoRenderer::chromaAltV() measures the reversal itself. Within each chroma
block it takes four lines of the same field — frame lines n, n+2, n+4,
n+6, since the frame that reaches the analyser is woven — averages Cb and Cr
along each, and returns the alternating part, (c₀ − c₁ + c₂ − c₃) / 4. Cb and
Cr rather than U and V so that both axes have the same span and can be compared
against one another.
A candidate is ruled out when both hold:
kAltFlipping |
V alternation at or above 0.005 |
kAltAxisRatio |
and more than 4× the U alternation |
Both are needed. Magnitude alone would fire on any picture with fine horizontal detail — but such detail alternates on both axes, and a reversed phase stands on V alone, which is what the ratio catches. The ratio alone would fire on noise, where both numbers sit near zero; the magnitude floor keeps it quiet there.
Twelve rounds per standard, on a GameCube putting out PAL 60:
| Candidate | V alternation | V / U |
|---|---|---|
| NTSC 4.43 (wrong) | 0.0070 – 0.0515 | 7.7 – 14.6 |
| PAL 60 (correct) | 0.0002 – 0.0026 | 0.5 – 2.0 |
| NTSC M | 0.0001 – 0.0005 | 0.4 – 0.8 |
| PAL M | 0.0001 – 0.0008 | 0.1 – 1.0 |
No overlap on either axis, with a factor of three to four in hand on both. Pinned to NTSC 4.43 and then asked ten times in a row: corrected on the first press and unchanged on the other nine. The build before this one got it wrong four times in nine.
This is a disqualification, ranking with tinted darks — a candidate that does this is not decoding worse, it is decoding the wrong signal — so it is out of both stages rather than merely behind in one.
Of the starting standard's two readings it takes the larger value, and deliberately does not follow the choice made for colour and darks. Those two depend on the scene, so which reading is the meaningful one is a real question. The alternation depends on the standard: a decoder that undoes the phase reversal correctly cannot suddenly show it in a second reading, and noise and flat scenes only push the number down. Whoever has it in either reading has it.
Two things it deliberately does not do. It does not fire on SECAM decoded as PAL: SECAM alternates which component each line carries, so both axes move and the ratio test stays silent — and that case is exactly what the darks rule was calibrated on. The two rules cover complementary failures rather than overlapping.
And it has only been measured in one direction — a PAL signal offered to an NTSC decoder. The mirror case, an NTSC signal offered to a PAL decoder, should produce the same signature for the same reason (the decoder inverts a line that was never inverted), and on a genuine NTSC source the dangerous rival is PAL M, whose subcarrier sits only 4 kHz away. But a decoder that averages adjacent lines to cancel phase errors would suppress the evidence, and whether this card does that is not known. The rule is written so that this costs nothing: it can only rule out, never promote. If it stays quiet, the decision falls back to colour and darks exactly as before, and it cannot fire on a correct standard because a matched decoder produces no alternation on either axis.
A round takes a few seconds and the picture keeps moving, so the starting standard is measured again at the end. If the two readings of the same standard disagree — either crossing one of the two thresholds, or differing by more than a factor of two — the scene moved and the comparison is void.
That guard was earned. On 31.08. at 02:02 a round began on a dark picture and ended on a colourful one: PAL 60 read 0.005 first and 0.122 last, and in between NTSC 4.43 took the round with 0.157 — against a GameCube that outputs PAL 60.
Of the two readings of the starting standard, the one with the cleaner darks counts. That is deliberately unequal, and the reason is measured: across 30.08., the darks of a wrong SECAM B varied by a factor of two while those of the correct PAL B varied by a factor of five. A beat from a wrong carrier lies evenly over every frame; real colour in dark areas depends entirely on the scene. A flat scene therefore makes the right candidate look bad, and moving away from a correct standard is the expensive mistake.
A void comparison is not a void measurement. If the round is discarded but the starting standard's own reading passes the same test the fast path uses — confident colour, neutral darks — that is the answer, and no repeat is needed. This is worth about three seconds: on 31.08. at 05:24 the round was discarded at 39.908 with PAL 60 reading 0.194 and darks 0.107, both well inside the thresholds, and the repeat at 42.573 established exactly what had already been on the line.
Then it is the scene. On 25.09 a blue background on a Switch in PAL B put every standard over the dark threshold. Nothing decided, the watch reopened the round six times, and once SECAM B was left standing: its blue cast suits a blue picture. Compared pair by pair on the same scene, the darks still separate:
| Standard | Colour | Dark regions |
|---|---|---|
| PAL B (correct) | 0.297 – 0.315 | 0.221 – 0.266 |
| SECAM B | 0.412 – 0.426 | 0.397 – 0.405 |
Since 5.2.1 there is a third stage for this case. The wrong carrier has to have
at least 1.3× as much in the darks (kTintedCleanerBy), and its extra in the
darks has to be at least 1.25× its extra in colour (kTintedExtraInShadows):
the added colour sits exactly where none belongs. Measured was 1.48 for both.
NTSC 4.43 against PAL 60 does not fall under it, because there the wrong
standard shows less everywhere.
After a comparison like this the watch does not open another round
(colourCompared_). The blue scene settled on PAL B in 1.5 s.
A scene that is nearly grey when decoded correctly cannot answer this, and is not made to. The round is repeated and then abandoned:
| Wait before repeating | Counts as an attempt | |
|---|---|---|
| Undecided — the scene is too colourless | 3 s, then 6 s | yes |
| Discarded — the picture moved during the round | 1 s each time | yes |
| Postponed — the screen is essentially black | next frame | no |
The doubling series is aimed at a grey scene, where waiting is the point: the scene has to become colourful. A discarded round is the opposite case — what was missing was not colour but stillness, and a racing game does not become calmer by waiting six seconds. The number of attempts is the same either way, so the visible disruption is unchanged; only the dead time between attempts shrinks.
After three attempts it is left alone and the starting standard stands. The log says which of the two reasons applied, because "the source is black and white" is a claim about the signal and must not be made when what was missing was stillness.
If no measurement comes back at all within kColourGiveUpSeconds (10 s), the
format has no readable chroma or too few frames are getting through. That is not
an error, only a no.
Everything above decides once per standard. Up to 5.1 that was not enough in one
place: when the one chance fell on a picture with nothing to decide. Double Dash,
switched from 50 to 60 Hz, shows mostly black around Lakitu for a long time. The
picture is lit enough to pass kChromaLitWanted but has too little colour to tell
anything apart. Three attempts come to nothing, the check gives up (probably
black and white), and the card stays on NTSC even when the most colourful race
is running ten seconds later.
The measurement that would show it keeps running anyway, every eighth frame, on analogue sources; on a digital one nothing reads it, so it does not run. So since 5.2 the settled standard is read along with it, without touching the standard. Reading it costs a few comparisons every three seconds. Three findings count, and each one on its own belongs to a wrong standard:
| Finding | Test |
|---|---|
| Colour flips from line to line |
kAltFlipping, as in the round |
| Colour down into the blacks | confident colour with tinted darks |
| A lit picture stays pale | at least 30 % lit, colour below kChromaPale (0.025) |
The third one is the delicate one, so it only applies to a standard that has
never shown strong, plausible colour. A standard that has decoded properly once
is not wrong on a snow track. Since 5.5.1 the second one follows the same rule: a
standard that has shown confident colour over real dark areas with clean darks
is not wrong on a dark red volcano. On DK Mountain the cannon flight reopened the
check every time (darks 0.214 to 0.244, after 0.074 to 0.138 on the same lock),
and the round confirmed PAL 60 each time. A wrong carrier never measured below
0.204. A proof without any dark areas proves nothing about the darks and does not
count. The threshold of the third finding sits below kChromaSuspect, because
the question here is not "is this suspect" but "is this clear". On 29.08. the
wrong standard measured 0.024 on snow and 0.013 in the desert, and the right one
0.037 on the snow.
-
Two windows in a row (just under six seconds) are a finding. One window is a picture; two are a state.
-
Once per lock the finding reopens the colour check, with the same window it was found in.
-
If the second check does not settle it, switching is no longer the automation's call. A notice on the picture says what it sees, with Find standard and Ignore:
- The colour flips from line to line — NTSC is probably wrong
- Hardly any colour under NTSC — the video standard may be wrong
Find standard runs the same search as the button in the Source tab. Ignore holds until the next lock. Tinted darks alone do not raise the notice: they are the softest of the three findings, and a check that has just confirmed the same standard has disproved them.
-
Strong, plausible colour at any point proves the standard, clears a notice and ends the watch.
The first pass of the round now also rejects colour that flips from line to line. On 31.08. NTSC 4.43 on a PAL 60 signal measured 0.099 colour with 0.031 in the darks. That passed both old tests, and the picture had the venetian-blind stripes of a missing PAL phase switch.
App::StandardSearchText(). Both stages are visible whether or not anything is
written on top of them — the standards are switched in front of you, and the
picture changes with each one. What is not visible is why it is happening, and
that part is measured. It is on screen as two lines over the picture:
Checking colour: PAL 60 (3/5) Colour reaches into the blacks — comparing the 4 standards with 525 lines (the first one twice)
The headline names the standard on screen right now and the step. The second line names the reason, of which there are three:
| Reason | What was measured |
|---|---|
| Colour unclear | chroma below kChromaConfident on a standard that could be right |
| Colour reaches into the blacks | dark-block chroma at or above kDarkTinted — the signature of a wrong carrier |
| Triggered by hand | F7, with nothing measurably wrong |
In stage one there is only one possible reason — the card does not lock on the standard that is set — so the counter carries most of the information: which candidate of how many is being tried. The second line names which of the two passes is running, with its deadline:
Scanning video standard: PAL B (1/4) Card does not lock — second pass, 1.25 s per standard
That is not a detail for the watcher. The same standard name comes round a second time, and without the line it looks as though the search is going in circles.
The colour round counts steps, not standards. Its candidate list carries the starting standard twice, once at the front and once at the end, so that the last measurement is taken under the same conditions as the first (see The scene does not wait). Counting standards would print "5 of 4"; counting steps and saying the first one twice in the line below prints something that adds up.
A counter matters more than it looks. A search without one is a search without an end — there is no way to tell whether it finishes in a second or in ten — and that is the difference between waiting and watching.
The overlay steps aside while the settings window is open, which says the same thing in its own line under the standard dropdown — Scanning: PAL 60 … — and in more detail besides, with the lock state and the live format next to it.
F7, or Detect video standard in the right-click menu.
App::RescanVideoStandard().
The automatic search has one blind spot, and it is not small. It acts when the lock is lost, and it acts when the colour measures wrong. A standard that holds its lock and shows plenty of colour with clean blacks is never doubted — the fast path takes it and nothing else runs. That is correct for the case it was built for and useless for the one it was not: colour that is wrong rather than missing. Grass in the wrong colour is, to every measurement on this page, colour.
A person sees it immediately. So there is a key for it.
F7 resets both stages: candidate index, sweep count, retry deadlines, and the colour round with them. The round it starts skips the fast path — that is the whole point, since the fast path is exactly what waves the suspect standard through. The log line says so, and so does the second line on screen.
The wish is held as a deadline, not a flag
(standardForceColourUntilQpc_, 30 s). Pressing F7 on a black picture produces
no round at all: nothing can be told apart on black, so the round waits for a
lit frame — that is the Postponed row in the table above, and it consumes no
attempt. A flag would then stand indefinitely, and the picture would start
cycling through standards two minutes later with nothing on screen to explain
it. A deadline expires on its own.
ResetStandardColourCheck() deliberately does not clear it. A graph rebuild
runs that reset, and a graph rebuild is exactly what tends to happen in the
second after the key is pressed.
A search started by hand owes an answer. It shows how it is searching, and when
it stops it puts the result in the same place for
kStandardResultSeconds (5 s):
Video standard: PAL 60 Corrected by colour — was NTSC 4.43
App::FinishManualStandardSearch(). Which exit a search takes is decided far
away from the key, and none of those places knows whether anybody is waiting on
it, so the wish is carried as a flag (standardManualSearch_) and every exit
calls the same function. Each says something different:
| How it ended | The second line |
|---|---|
| The round changed the standard | Corrected by colour — was NTSC 4.43 |
| The round confirmed it | The colour confirms it — no change |
| The measurement alone was enough | The colour checks out — no change |
| The round was void but the reading stood on its own | The comparison was unusable, but the colour stands on its own — no change |
| Nothing to compare against at this line count | No other standard with 525 lines — no change |
| Undecided, and another attempt is coming | The scene has too little colour — trying again in 3 s |
| Undecided after three attempts | Nothing decides — the source is probably black and white |
| Discarded three times over | The picture moved every time — no reliable comparison |
| The picture stayed black past the 30 s deadline | The picture stayed too dark to compare — no change |
| No standard locked at all | No standard locks — there is probably no signal |
The first answer wins. After that the question is answered, and anything later — a retry that decides ten seconds afterwards — belongs to the automatic search again, with its toast. Those two never appear together: a toast is a notice about something that happened by itself, and showing both would say the same thing twice in two places.
The result also steps aside rather than covering anything. It is shown only while no search is running, so if the lock is lost inside those five seconds the automatic search starts over and takes the overlay back — at which point the result is no longer true anyway.
Between the lock and the round there is a stretch where no standard is being switched and something is nevertheless happening: the colour is being measured, or the round is waiting for a picture with light in it. That stretch has its own line — Checking video standard: PAL 60, and underneath either Measuring the colour or The picture is too dark to compare — waiting. Without it a search started by hand looks finished several seconds before it is.
Three cases are refused, each with a notice rather than silence — a key that appears to do nothing looks broken:
| Case | Notice |
|---|---|
| Capture not running | No source is running. |
| Input is not analogue | Only analogue inputs have a video standard. |
| The profile pins a standard | The video standard is fixed — set it to Automatic to search. |
The last one is the interesting refusal. A fixed standard is a decision somebody made, and a key that overturns it in passing would be a surprise. It stays fixed; the notice says what to change if that is not what was wanted.
The route to all of this used to be picking a fixed standard in the dropdown and setting it back to automatic. That works, and nobody finds it who does not already know it.
UpdateCropForFormat(). A crop is a count of source pixels — cropLeft = 20
means 20 of 720 — so it stops meaning anything the moment the line count
changes. When the source size changes, the crop is set to zero, the old values
are written to the log, and a notice says Video format changed (720×480) — crop
reset.
It is deliberately not re-measured automatically. The moment a standard
changes is the worst possible moment to measure a border: the graph has just
been rebuilt, the console is often mid-boot, and a logo on black is exactly the
case DetectCrop's own sanity guard refuses. Sending the measurement into its
own guard would be self-defeating. Detect is a keystroke away (F8) for when
there is a real picture to measure.
A console that keeps changing between 50 and 60 Hz then wants its border measured twice over, every time. Remember per picture size in the image settings keeps one crop per source size instead, so the switch that used to throw the crop away now puts the other one back. See Cropping and geometry.
A detected standard can also pick the profile. That is a property of the profile rather than of the search — it is set in the profiles tab and described in Configuration and profiles — but it is this page's second stage that triggers it: the switch happens when the colour round has settled, not when the lock comes in, because until then the standard is only a line count.
Measured 31.08.2026, GameCube at 60 Hz, card forced to PAL B beforehand so the search has to find its way out. From the first line of the search to the final colour verdict:
05:27:23.890 search starts, region default is PAL B
05:27:25.591 PAL B set
05:27:26.797 no frame for 2.9 s -- PAL B cannot decode this signal
05:27:26.797 PAL B discarded after 1.27 s without lock
05:27:26.831 PAL 60 set
05:27:27.056 locked (0.26 s)
05:27:27.169 graph rebuilt, 720x480
05:27:30.226 PAL 60 has clear colour (0.192), darks neutral (0.107)
6.3 seconds, of which 3.1 is the single colour measurement that confirms the result. The run before the last two fixes took 13.0 s for the same sequence, and before that, from a lost lock, 11.6 s.
That run predates the two passes. In it, PAL B — the wrong candidate — was discarded after 1.27 s; in the fast pass it gets 0.6, and every further wrong candidate the same.
The colour measurement at the end is untouched by any of it — the adaptive settle above shortened the round, not this. That is deliberate rather than overlooked: it runs at the background cadence, ten frames at every eighth, and what it decides is whether a live picture is grey. Ten frames spread across eighty are a sample of the scene; three consecutive frames are one moment of it. The round can afford three because a wrong reading there costs one more window and nothing else, while here it would be the whole answer. The dense cadence is switched on for a search started by hand and for the round itself — not for this.
- The lock is horizontal only. On this hardware some standards report a lock with nothing connected at all, which is why stage two exists and why a pass that finds nothing parks the card on the best guess rather than the last one tried.
- A source that is black forever is never resolved beyond its line count, because the wait above never ends. That is deliberate — the alternative is a verdict reached on no evidence — but it means a permanently dark input keeps whatever the lock gave it.
- A black-and-white source cannot be resolved beyond its line count. After three attempts the region default stands. This is correct — there is nothing in the picture to decide with — but it means a monochrome source may sit on PAL B where PAL N would do equally well.
- NTSC M and NTSC M (Japan) are not distinguished. They differ in the setup pedestal, a brightness property; telling them apart would need a different measurement than this one.
- The alternation test is calibrated in one direction only — a PAL signal offered to an NTSC decoder. It should hold in reverse for the same physical reason, but that has not been measured, and a decoder that averages adjacent lines could hide the evidence. It can only rule a candidate out, so the cost of it staying quiet is the older behaviour and nothing worse.
- Everything here was measured on one card, a StarTech PEXHDCAP60L (SA7160), against a GameCube over composite. The thresholds are grounded in that hardware.