Repository navigation
1.5.0 — BRAW container metadata, ExifTool/ffprobe parity
Added
- Blackmagic RAW (
.braw) container metadata — new format support routed throughMP4Parser. BRAW is an ISOBMFF derivative with the legacy QuickTime layout (wide+mdathead,moovtail-placed, noftyp); the parser tolerates the missingftypand themdtadecoder grew handlers for BRAW's typed payloads including the BMD-specific type 71 (float32-BE pair) used for rectangle fields. Surfaces toCameraMetadata: camera make/model + firmware, color science generation, viewing gamma + gamut, compression ratio, shutter type; off-speedcaptureFps(distinct from the mvhd/stts-derivedframeRate); production slate (clip number / scene / take / reel / camera / environment / day-night); sensor area, crop / safe-area rectangles, LUT used, post-3DLUT mode, embedded LUT name, frameguide aspect ratio, gamut compression. Per-frame interpretation (white point, tint, absolute ISO, shutter angle) lives in proprietarybfdn/ctrnboxes inside the codec sample entry and remains unparsed. Verified against Pyxis 12K / 6K and Cinema 6K samples. - MPEG-TS bitstream decoding —
MPEGReadernow decodes inline H.264 / HEVC SPS, AAC ADTS frame headers, and PCR timestamps directly from Transport Stream packets, surfacing pixel format, profile/level, framerate, sample rate, channel layout, and timing on.ts/.m2tsfiles without ffprobe. NewMPEGBitstream.swifthouses the bit-readers (Exp-Golomb, NAL emulation-prevention unescaping, ADTS frame parsing). - SMPTE ST 377-4 MCA audio labels for MXF — multichannel audio labeling per SMPTE ST 377-4 is now decoded out of MXF audio descriptors. New
MCAAudioLabeling,MCALabelsRenderer,MXFMCAReader, surfaced throughVideoStream/VideoMetadataand the JSON exporter. New CLI subcommandswift-exif mxf-labelsemits a bmx-compatiblelabels.txtround-trip for production audio workflows. - Apple ecosystem support (Phase 18) —
AppleMakerNote.swift(iPhone MakerNote: lens model, ContentIdentifier, image stabilization, HDR mode, …),AAESidecar.swift(Apple Photos.aaeadjustment XML),HEIFAuxiliaryImages.swift(depth maps, alpha mattes, HDR gain maps via shared ISOBMFF / iloc), and Live PhotoContentIdentifiersurfaced fromMP4Parser. - Pentax, Leica, and Sigma MakerNote parsers — three additional vendor MakerNote implementations with matching writer support and round-trip test coverage.
- ExifTool / ffprobe parity initiative —
PARITY_PLAN.mdplus the first phases:- HEIC parity (Phase 1) —
infe-drivencontent_type, explicitmeta → iprp → ipcowalk, top-levelcolrfallback. - JPEG XL (Phase 2) — decode
SizeHeaderfrom the JXL codestream soFile:ImageWidth/Heightare populated. - MP4 streams (Phase 3.1 / 3.2 / 3.5) — preserve track declaration order in
streams, surface data tracks, hoist chapter tracks out ofstreamsinto a siblingchaptersarray. - MP3 / M4A streams (Phase 3.3) — emit a single synthetic audio stream from
--streamsto match ffprobe. - MKV track order (Phase 3.4) — preserve Matroska track declaration order.
- GPS / subtitle codec cosmetics (Phase 4) — render GPS coordinates with degree signs, alias
tx3gtomov_text.
- HEIC parity (Phase 1) —
Changed
- Format-level
durationnow matches ffprobe. Previouslyformat.durationwasmvhdverbatim; mvhd is the longest mdhd of any track, so files likeChapterMarkerDualSubtitle.mp4reported 98.691 s while audio/video both ended at ~71.16 s. The MP4 reader now caps mvhd atmax(audio, video)when subtitle/data tracks inflate it, and keeps the smaller mvhd value untouched when edit-list trimming legitimately makes it shorter than the longest essence stream. - Audio file
format.bit_ratenow matches ffprobe. For MP3 / M4A / FLAC, the containerbit_rateis now derived asfile_size × 8 / duration(whole-file rate including container overhead and AAC priming/postroll padding) instead of the audio stream's declared rate. - MXF and MPEG-TS per-stream
Duration. MXF essence descriptors and MPEG-TS streams don't carry per-track durations the way MP4 does. The format-level duration is now propagated to streams that don't already have one (matching ffprobe behaviour); legitimate per-stream durations are never overwritten. - GPMF SCAL divisor lookup is now hoisted out of the per-sample GPS5 loop in
GPMFReader— pure refactor, behavior preserved.
Fixed
- GIF parser sub-block handling — regression tests added covering the earlier sub-block-overrun hardening (truncated extension blocks, malformed image descriptors, unterminated sub-block chains).
Tests
1420 tests, 0 failures (26 skipped), covering BRAW slate extraction across Pyxis 12K / 6K / Cinema 6K, the new MakerNote families, MXF MCA round-trip via bmx, MPEG-TS bitstream parity vs ffprobe, and HEIF auxiliary image extraction.