Extract RecordingPipeline from CameraViewController (UI modernization PR 9)#132
Merged
Merged
Conversation
… PR 9) Mechanical move, no behavior/threading changes: RecordingPipeline (non-UI) now owns the asset writer and its inputs, the six-boolean recording state machine, the writing queue, per-frame write/crop, and saving/sending the finished movie. The VC stays the sample-buffer delegate (captureOutput fans out to the frame streamers, which are live preview, not recording) and keeps the microphone-permission flow, forwarding recording frames to the pipeline. Seams: sendMessage (actor relay for the start ack, stop response and video resource — captures the session ref, not the VC), onRecordingStarted/Stopped (timer overlay), onModeChanged (idle vs recording chrome), onError, onPhotosAccessDenied. CameraViewController: 962 -> 632 lines. New device-free tests cover asset writer input setup including the even-rounded 4:3 crop rect and the stop-while-idle guard. 385/385 tests green (381 + 4 new). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New-code cleanups from the senior Swift review: tighten access control on the pipeline (assetWriter/videoCropContext/writeSampleBuffer private, pixelBufferAdaptor/cachedVideoCropRect private(set)), document that onError fires on the writing queue, name the idle condition at both onModeChanged call sites, and use XCTUnwrap instead of force-unwraps in the tests. Also three pre-existing one-liners the extraction surfaced: guard the missing-microphone case so it reaches the record-without-audio fallback instead of crashing on audioDevice!, wire the silent startWriting() failure to onError, and drop two DEBUG prints from production paths. 385/385 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
PR 9 of the UI modernization series: the recording/sample-buffer pipeline moves out of
CameraViewControllerinto a new non-UIRecordingPipeline, following the exact playbook of PR 8'sCaptureEngineextraction — mechanical move, no behavior or threading changes, closure seams back to the VC, full suite green as the gate.CameraViewControllerdrops from 962 → 632 lines. With capture (PR 8) and recording (this PR) both out, what remains is real UI plus the frame streamers — the runway for the PR 10 SwiftUI chrome.What moved
RecordingPipeline(407 lines, zero UIKit) now owns:isRecording,recordingWillBeStarted/Stopped,readyToRecordVideo/Audio) — moved intact, not redesigned; the redesign stays queued behind the single-owned-queue threading fixWhat stayed in the VC — and why
captureOutputfans out to two consumers — frame streaming (live preview, not recording) and the recording path. The VC keeps the delegate and forwards recording frames topipeline.processFrame; the audio delegate is passed intopipeline.startRecording(audioSampleBufferDelegate:)the same way PR 8 passes it intoengine.setupCamera.Seams
sendMessage— a single actor relay for the start ack, stop response, and video resource. It captures thesessionref (not the VC), carrying over PR 8's teardown-safety guarantee: an in-flight recording still reaches the actor if the VC deallocates. It also made the pipeline's no-op guards directly assertable (inject a recorder, assert nothing was sent).onRecordingStarted/Stopped(timer overlay),onModeChanged(idle vs recording chrome),onError,onPhotosAccessDenied.Tests
385/385 green (381 existing + 4 new). The loopback video round-trips — including the 3-step stop protocol and the start-ack forwarding fixed in PR 8 — passed unchanged across the move, which is the point of the safety net.
New device-free
RecordingPipelineTests:Explicitly deferred (unchanged from the queued list)
Single owned serial queue (threading fix),
RotationCoordinator(iOS 17) /maxPhotoDimensions(iOS 16) migrations, frame-streaming extraction, SwiftUI chrome (PR 10+).🤖 Generated with Claude Code