A DPX frame that DaVinci Resolve reads without complaint and ffmpeg refuses:
[dpx] Descriptor 60 is not implemented. ... patches welcome
Same on ffmpeg 7.1 and 8.1. libavcodec/dpx.c implements descriptors 1, 2, 3, 4, 6, 50, 51, 52, 100,
102, 103 only. SMPTE ST 268-1:2014 lists 53–99 as Reserved, and ST 268-2:2023 Table 10 fills in just
53–58 (plus 10, 11, 104, 105). Descriptor 60 is defined nowhere published.
This repository exists so the layout does not have to be reverse engineered twice.
A v210-style 10-bit YCbCr 4:2:2 payload, despite the element header saying packing = 1
("filled, method A").
The catch, and the reason a straightforward reader produces stripes: the header is big-endian
(SDPX) while the image words are little-endian. Read each 32-bit word little-endian and it holds
three right-aligned 10-bit fields in bits 0–9, 10–19, 20–29. Four words cover six pixels:
word 0: Cb0 Y0 Cr0
word 1: Y1 Cb2 Y2
word 2: Cr2 Y3 Cb4
word 3: Y4 Cr4 Y5
Flattened, the stream is Cb Y Cr Y Cb Y Cr Y …, chroma subsampled 2:1 horizontally. Rows are
progressive and contiguous: 1280 words (5120 bytes) per row, 1080 rows, no EOL or EOI padding.
Colour is limited-range Rec.709. Established from the file rather than assumed: a plateau in the
green STBY mark reads Y/Cb/Cr = 676/172/114, which Rec.709 limited turns into RGB 0/249/0, while
swapping Cb/Cr gives 26/244/0 and Rec.601 gives a clipped 19/255/7. The header's transfer = 1
and colorimetric = 2 are not useful for choosing the matrix.
The first two payload words show why an empty frame looks like a three-pixel pattern rather than a 4:2:2 one:
bytes, big-endian display : 00020120 40000804
read little-endian : 512 64 512 | 64 512 64
That is neutral chroma (512) alternating with legal-range black (64) — three black pixels.
| file | what it is |
|---|---|
RL01_00411952.dpx |
the plate. 1920×1080, 10-bit, descriptor 60, written by DaVinci in 2023. An ARRI camera monitor capture: near-black frame with a UI overlay |
decode_descriptor60.mjs |
dependency-free Node decoder, DPX → PNG |
decoded_preview.png |
what it should look like when decoded correctly |
node decode_descriptor60.mjs RL01_00411952.dpx out.png
Mean absolute horizontal luma-neighbour difference after a correct decode is 4.687. Every incorrect interpretation tried along the way scored 243–408, so that number is a usable check.
- No published specification assigns descriptor 60 this meaning. The honest description is "DaVinci's private descriptor-60 v210 variant", not a general DPX definition. A decoder should validate the payload rather than trust the tag.
- One frame proves the layout of this file. It does not prove every DaVinci descriptor-60 file uses the same matrix, range or padding.
- Chroma is upsampled here by pair replication, which is faithful to the stored samples but makes no claim about the producer's chroma siting or reconstruction filter.
The plate contains no project or copyright metadata (both fields empty) and no filmed content — it is a monitor capture of an empty frame. Kept as-is, byte for byte, so it can serve as a test fixture.
Worked out jointly by two AI agents (Claude Opus 5 and OpenAI Codex) against the file itself: the geometry and the two-components-per-pixel arithmetic on one side, the little-endian payload and the matrix verification on the other. Written up because the next person to meet a descriptor-60 plate should not have to repeat it.