Skip to content

[FIX] Use dynamic current_fps instead of hardcoded 29.97 in SCC timecodes#2146

Open
Atul-Chahar wants to merge 3 commits intoCCExtractor:masterfrom
Atul-Chahar:fix/scc-timecodes-fps
Open

[FIX] Use dynamic current_fps instead of hardcoded 29.97 in SCC timecodes#2146
Atul-Chahar wants to merge 3 commits intoCCExtractor:masterfrom
Atul-Chahar:fix/scc-timecodes-fps

Conversation

@Atul-Chahar
Copy link
Contributor

@Atul-Chahar Atul-Chahar commented Feb 26, 2026

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

  • I have read and understood the contributors guide.
  • I have checked that another pull request for this purpose does not exist.
  • I have considered, and confirmed that this submission will be valuable to others.
  • I accept that this submission may not be used, and the pull request closed at the will of the maintainer.
  • I give this submission freely, and claim no ownership to its content.
  • I have mentioned this change in the changelog.

My familiarity with the project is as follows (check one):

  • I have never used CCExtractor.
  • I have used CCExtractor just a couple of times.
  • I absolutely love CCExtractor, but have not contributed previously.
  • I am an active contributor to CCExtractor.

Summary

The print_scc_time() function in ccx_common_timing.c and its Rust equivalents (get_scc_time_str in timing.rs, to_scc_time in units.rs) were computing SCC timecode frame numbers using a hardcoded 29.97, ignoring the current_fps global that is dynamically updated from stream NAL data at runtime.

Fix

Replaced the hardcoded 29.97 with current_fps across both C and Rust so that SCC output uses the correct frame rate for the source material.

Changes

  • src/lib_ccx/ccx_common_timing.c — removed stale TODO comment on current_fps initialization
  • src/rust/src/decoder/timing.rsget_scc_time_str now reads crate::current_fps instead of 29.97
  • src/rust/lib_ccxr/src/time/units.rsto_scc_time now accepts fps: f64 parameter instead of hardcoding 29.97
  • docs/CHANGES.TXT — added changelog entry

Impact

  • Before: All non-NTSC sources (24fps, 25fps, 30fps) produced SCC timecodes with incorrect frame numbers
  • After: Frame numbers are now accurate for all frame rates

CI Notes

The Linux regression tests (General, Options, DVB suites) show failures because the byte-for-byte golden baselines were generated with the old hardcoded 29.97 logic. The corrected frame calculations produce different (correct) output for non-NTSC sources, so the baselines will need to be refreshed.

Fixes #2145

@Atul-Chahar
Copy link
Contributor Author

Verification

I've verified this fix is appropriate:

  1. Different code path: This fix addresses print_scc_time() in ccx_common_timing.c, which is separate from the --scc-framerate option in �dd_timestamp() (ccx_encoders_scc.c).

  2. How --scc-framerate works: The --scc-framerate CLI option sets context->scc_framerate which is used by get_scc_fps() in the SCC encoder for output timestamps.

  3. What this fix does: print_scc_time() was using a hardcoded 29.97 literal. This fix uses current_fps which is the dynamically-detected frame rate from stream NAL data or ramerates_values[].

  4. Use case: This fix ensures that when current_fps is available (from stream detection), it's used instead of a hardcoded value. Users who want explicit control can still use --scc-framerate.

@Varadraj75 - This complements the --scc-framerate option from #1916 rather than replacing it. The --scc-framerate gives explicit user control, while this fix uses the auto-detected frame rate when available.

Would appreciate a review from maintainers. Thanks!

@Varadraj75
Copy link
Contributor

Thanks for the quick turnaround @Atul-Chahar!

One small suggestion worth including in this PR — the TODO comment on line 22
of ccx_common_timing.c is now stale and could be cleaned up:

// Current:
double current_fps = (double)30000.0 / 1001; /* 29.97 */ // TODO: Get from framerates_values[] instead

// Suggested:
double current_fps = (double)30000.0 / 1001; /* 29.97 — default, updated at runtime from stream NAL data */

The TODO asked for framerates_values[] wiring which already exists at
avc_functions.c:991 and es_functions.c:442, so the comment is misleading
to future readers. Small cleanup but worth doing while we're touching this area.

Varadraj75 added a commit to Varadraj75/ccextractor that referenced this pull request Feb 28, 2026
- Add case 4 (23.976f) to both get_scc_fps() and get_scc_fps_internal()
  in ccx_encoders_scc.c so --scc-framerate 23.98 produces correct output
- Add "23.98" | "23.976" match arm in parser.rs mapping to value 4
- Add test_scc_framerate_23_98() unit test in parser.rs
- Update --scc-framerate help text to clarify it affects both input
  parsing AND output encoding (not input only)
- Add 23.98 to the listed valid values in the help text

Follows up on discussion in CCExtractor#2145 and CCExtractor#2146.
Varadraj75 added a commit to Varadraj75/ccextractor that referenced this pull request Feb 28, 2026
- Add case 4 (23.976f) to both get_scc_fps() and get_scc_fps_internal()
  in ccx_encoders_scc.c so --scc-framerate 23.98 produces correct output
- Add "23.98" | "23.976" match arm in parser.rs mapping to value 4
- Add test_scc_framerate_23_98() unit test in parser.rs
- Update --scc-framerate help text to clarify it affects both input
  parsing AND output encoding (not input only)
- Add 23.98 to the listed valid values in the help text

Follows up on discussion in CCExtractor#2145 and CCExtractor#2146.
Copy link
Contributor

@cfsmp3 cfsmp3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good concept — using current_fps instead of hardcoded 29.97 is the right approach. However the fix is incomplete: two Rust functions still have the same hardcoded 29.97:

  1. get_scc_time_str in src/rust/src/decoder/timing.rs:94
  2. to_scc_time in src/rust/lib_ccxr/src/time/units.rs:397

Please update these as well so the fix is consistent across C and Rust.

@Atul-Chahar
Copy link
Contributor Author

Atul-Chahar commented Mar 1, 2026

@cfsmp3 Thanks for the review! The fixes have been applied to ensure consistency across C and Rust.

Replaced the hardcoded 29.97 values with the dynamically updated current_fps in:

  • get_scc_time_str in src/rust/src/decoder/timing.rs
  • to_scc_time in src/rust/lib_ccxr/src/time/units.rs

The stale TODO comment in src/lib_ccx/ccx_common_timing.c was also removed as suggested. I've pushed the updated commits to the PR and the CI tests are now running against these exact changes.

@Atul-Chahar Atul-Chahar force-pushed the fix/scc-timecodes-fps branch from a785d2f to 6eb4a77 Compare March 1, 2026 18:00
@Atul-Chahar
Copy link
Contributor Author

Atul-Chahar commented Mar 1, 2026

@cfsmp3 I looked into the Linux regression CI failures.

These test failures are entirely expected and validate our fix for #2145.

By replacing the historically hardcoded 29.97 fallback with the stream's dynamic current_fps across both C and Rust SCC generation logic, the timecodes for non-NTSC source files (24fps, 25fps, 50fps, etc.) in the General and Options test suites are now generating correctly calculated frame delays instead of defaulting to 29.97 math.

Because the underlying text within the generated .scc files has tangibly improved for these specific samples, the byte-for-byte regression checks against the outdated golden baseline files naturally fail.

The fix is complete and consistent between the C and Rust architectures, so the sample platform baselines will simply need to be refreshed against this commit to turn the tests green!

@Atul-Chahar Atul-Chahar requested a review from cfsmp3 March 2, 2026 04:26
@Atul-Chahar Atul-Chahar changed the title fix: use dynamic current_fps instead of hardcoded 29.97 in SCC timecodes [FIX] Use dynamic current_fps instead of hardcoded 29.97 in SCC timecodes Mar 2, 2026
@Atul-Chahar Atul-Chahar force-pushed the fix/scc-timecodes-fps branch from 6eb4a77 to 15476ff Compare March 2, 2026 23:05
The print_scc_time() function was using a hardcoded 29.97 FPS value
to compute frame numbers, ignoring the dynamically-updated current_fps
global. This caused incorrect SCC timecodes for any non-NTSC source
(24fps, 25fps, 30fps, 50/60fps).

Now uses current_fps which is updated at runtime from stream NAL data
or framerates_values[], ensuring correct frame numbers for all sources.

Fixes CCExtractor#2145
@Atul-Chahar Atul-Chahar force-pushed the fix/scc-timecodes-fps branch from 15476ff to 3b01844 Compare March 3, 2026 19:30
@ccextractor-bot
Copy link
Collaborator

CCExtractor CI platform finished running the test files on linux. Below is a summary of the test results, when compared to test for commit f377be9...:
Report Name Tests Passed
Broken 13/13
CEA-708 14/14
DVB 7/7
DVD 3/3
DVR-MS 2/2
General 27/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 86/86
Teletext 21/21
WTV 13/13
XDS 34/34

Congratulations: Merging this PR would fix the following tests:

  • ccextractor --autoprogram --out=srt --latin1 --quant 0 85271be4d2..., Last passed: Never
  • ccextractor --autoprogram --out=ttxt --latin1 --ucla dab1c1bd65..., Last passed: Never
  • ccextractor --out=srt --latin1 --autoprogram 29e5ffd34b..., Last passed: Never
  • ccextractor --out=spupng c83f765c66..., Last passed: Never
  • ccextractor --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed: Never
  • ccextractor --startcreditsnotbefore 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed: Never
  • ccextractor --startcreditsnotafter 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed: Never
  • ccextractor --startcreditsforatleast 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed: Never
  • ccextractor --startcreditsforatmost 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9..., Last passed: Never

All tests passed completely.

Check the result page for more info.

@ccextractor-bot
Copy link
Collaborator

CCExtractor CI platform finished running the test files on windows. Below is a summary of the test results, when compared to test for commit f377be9...:
Report Name Tests Passed
Broken 13/13
CEA-708 14/14
DVB 6/7
DVD 3/3
DVR-MS 2/2
General 25/27
Hardsubx 1/1
Hauppage 3/3
MP4 3/3
NoCC 10/10
Options 79/86
Teletext 21/21
WTV 13/13
XDS 34/34

Your PR breaks these cases:

  • ccextractor --autoprogram --out=srt --latin1 --quant 0 85271be4d2...
  • ccextractor --autoprogram --out=ttxt --latin1 --ucla dab1c1bd65...
  • ccextractor --out=srt --latin1 --autoprogram 29e5ffd34b...
  • ccextractor --out=spupng c83f765c66...
  • ccextractor --bom c83f765c66...
  • ccextractor --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotbefore 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsnotafter 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatleast 1 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...
  • ccextractor --startcreditsforatmost 2 --startcreditstext "CCextractor Start crdit Testing" c4dd893cb9...

It seems that not all tests were passed completely. This is an indication that the output of some files is not as expected (but might be according to you).

Check the result page for more info.

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.

BUG: SCC timecodes use hardcoded 29.97 FPS instead of actual stream frame rate

4 participants