Skip to content

refactor(processor): serialize AVFilterGraphFree calls with mutex for loudnorm concurrency safety#101

Merged
flexiondotorg merged 2 commits into
mainfrom
filter-mutex
Jun 2, 2026
Merged

refactor(processor): serialize AVFilterGraphFree calls with mutex for loudnorm concurrency safety#101
flexiondotorg merged 2 commits into
mainfrom
filter-mutex

Conversation

@flexiondotorg
Copy link
Copy Markdown
Contributor

  • Introduce process-global graphFreeMu mutex to serialize all AVFilterGraphFree calls
  • Add freeFilterGraphLocked helper that acquires lock before free in normalise.go
  • Route all 8 production free sites through freeFilterGraphLocked (frame_processor, analyzer, analyzer_output, processor)
  • Extend loudnorm capture bracket (startLoudnormCapture/stopLoudnormCapture) to hold graphFreeMu lock across entire
    raise→install→free→parse→restore span
  • Fold lifecycleMu into graphFreeMu (superset covers all graph-free exclusion, eliminates redundancy)
  • Extract inline filter literal at analyzer_output.go:40 to package-level constant outputRegionAnalysisFilterFormat for guard test reuse
  • Add normalise_guard_test.go with TestMetadataModeGuard and TestLoudnormCaptureExcludesConcurrentGraphFree assertions

These changes make loudnorm JSON capture safe under parallel multi-file processing. Serial path unchanged; verified under -race.

Verify that FFmpeg's ebur128 filter under metadata=1 emits zero
AV_LOG_INFO lines during frame processing, with all ~47 lines (ebur128 +
astats) deferred to graph teardown. Control run confirms metadata=0
produces 33,000 mid-loop lines, validating that metadata mode suppresses
per-frame framelog.

Confirms Option 1 (single process-wide mutex around AVFilterGraphFree)
is sufficient for concurrent multi-file processing. Test gracefully
skips if testdata/fixture-5m.flac is absent.

Signed-off-by: Martin Wimpress <code@wimpress.io>
… loudnorm concurrency safety

- Introduce process-global graphFreeMu mutex to serialize all
  AVFilterGraphFree calls
- Add freeFilterGraphLocked helper that acquires lock before free in
  normalise.go
- Route all 8 production free sites through freeFilterGraphLocked
  (frame_processor, analyzer, analyzer_output, processor)
- Extend loudnorm capture bracket
  (startLoudnormCapture/stopLoudnormCapture) to hold graphFreeMu lock
  across entire raise→install→free→parse→restore span
- Fold lifecycleMu into graphFreeMu (superset covers all graph-free
  exclusion, eliminates redundancy)
- Extract inline filter literal at analyzer_output.go:40 to
  package-level constant outputRegionAnalysisFilterFormat for guard test
  reuse
- Add normalise_guard_test.go with TestMetadataModeGuard and
  TestLoudnormCaptureExcludesConcurrentGraphFree assertions

These changes make loudnorm JSON capture safe under parallel multi-file
processing. Serial path unchanged; verified under -race.

Signed-off-by: Martin Wimpress <code@wimpress.io>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 7 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Requires human review: This PR introduces a global mutex to serialize AVFilterGraphFree calls across the processor package, affecting core concurrency and locking patterns; despite clean AI review, such refactors carry risk of deadlocks or performance regressions in production paths and require human judgment to validate.

Re-trigger cubic

@flexiondotorg flexiondotorg merged commit f925c2f into main Jun 2, 2026
16 checks passed
@flexiondotorg flexiondotorg deleted the filter-mutex branch June 2, 2026 16:44
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