Skip to content

[FIX] Fix zero timestamps for GXF/MXF ancillary captions - #2390

Merged
cfsmp3 merged 1 commit into
masterfrom
fix/gxf-anc-timestamps
Oct 18, 2026
Merged

cfsmp3 merged 1 commit into
masterfrom
fix/gxf-anc-timestamps

Conversation

@cfsmp3

@cfsmp3 cfsmp3 commented Oct 18, 2026

Copy link
Copy Markdown
Contributor

In raising this pull request, I confirm the following (please check boxes):

Reason for this PR:

  • This PR adds new functionality.
  • This PR fixes a bug that I have personally experienced or that a real user has reported and for which a sample exists.
  • This PR is porting code from C to Rust.

Sanity check:

  • I have read and understood the contributors guide.
  • I have checked that another pull request for this purpose does not exist.
  • If the PR adds new functionality, I've added it to the changelog. If it's just a bug fix, I have NOT added it to the changelog.
  • I am NOT adding new C code unless it's to fix an existing, reproducible bug.

Repro instructions:

Generate the synthetic GXF from #2373 (python3 gen_gxf_anc.py anc.gxf, one CEA-608 caption in an SMPTE 291 ancillary track) and run ccextractor anc.gxf --out=srt -o out.srt. On master nothing is written ("Deleted empty output file"); with this PR: 00:00:00,401 --> 00:00:02,468 GXF ANC TEST.


GXF and MXF hand caption data to process_data() as CCX_RAW_TYPE buffers, with no video frames to anchor the timing. The caller has already called set_current_pts() for the packet, which sets pts_set to 1, and set_fts() only reaches MinPtsSet after seeing a video frame type — so the CCX_RAW_TYPE branch's pts_set == 0 check never fired and min_pts was never established. fts stayed at 0, so every GXF ancillary cue had zero length and SRT output was empty; on MXF the first cues were stamped 0 until timing got established a few seconds in.

This sets min_pts in that branch whenever MinPtsSet hasn't been reached, from timing->current_pts (already rescaled to 90 kHz by the caller; data_node->pts is in GXF frame units).

Only GXF and MXF reach this: the third CCX_RAW_TYPE producer, the FFmpeg integration, never sets a PTS, and CCX_RAW inputs (DVR-MS/ASF, RCWT) use a different branch.

Synthetic GXF, 3 captions master this PR
525i, 29.97 fps no output 0.434–2.501, 4.372–5.938, 8.976–10.042 (exact vs generator)
625i, 25 fps no output 0.521–2.999, 5.241–7.119, 10.761–12.039
HD (field size 6340), 59.94 fps no output 0.217–1.250, 2.186–2.968, 4.488–5.020

On a real MXF sample, the first two cues (608 at 0.001/2.486, 708 at 0.001/0.001) become 0.667/2.803 and 0.533/2.803, now agreeing between 608 and 708; all later cues are unchanged. Local GXF, MXF, raw, bin and RCWT samples are otherwise byte-identical to master, and ASan is clean.

GXF and MXF hand caption data to process_data() as CCX_RAW_TYPE
buffers with no video frames to anchor the timing. The caller has
already run set_current_pts() for each packet, which sets pts_set to
1, and set_fts() only reaches MinPtsSet after seeing a video frame
type, so the CCX_RAW_TYPE branch's "pts_set == 0" check never fired
and min_pts was never established. fts stayed at 0, every GXF
ancillary cue had zero length and SRT output was empty; MXF's first
cues were stamped 0 until timing was set some seconds in.

Establish min_pts in that branch whenever MinPtsSet hasn't been
reached, and take it from timing->current_pts, which the caller has
already rescaled to 90 kHz (data_node->pts is in GXF frame units).
@cfsmp3
cfsmp3 merged commit 83801f5 into master Oct 18, 2026
46 of 48 checks passed
@cfsmp3
cfsmp3 deleted the fix/gxf-anc-timestamps branch October 18, 2026 04:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant