Sample CodemacOSReviewed 2026-07-21View on Apple Developer

Converting projected video to Apple Projected Media Profile

At a glance

Item Summary
Purpose Classify projected-media input and transcode it to the Apple Projected Media Profile delivery variant.
App architecture Three-part command-line pipeline: argument orchestration, optional classification, and media conversion.
Main patterns Command, classifier, immutable pipeline owner, and metadata data carrier.
Project style One executable target with three primary Swift files and no UI or persistence layer.

Project structure

ProjectedMediaConversion/
├── ProjectedMediaConversion.swift  # CLI, validation, output naming
├── ProjectedMediaClassifier.swift  # Input format inspection
└── Converter.swift                  # Reader, conversion, and writer pipeline

Structure observations

  • File names align with the three runtime responsibilities.
  • The command creates short-lived collaborators; APMPConverter retains only source-reading state.
  • There are no app-defined protocols or nested architectural folders.

Overall architecture

Reference code

ProjectedMediaConversion/ProjectedMediaConversion.swift:47 — command orchestration

mutating func run() async throws {
    // ... optionally classify input ...
    let converter = try await APMPConverter(from: inputURL)
    try await converter.convertToAPMP(
        output: outputURL,
        projectedMediaMetadata: projectedMediaMetadata
    )
}

Interpretation

The entry type owns policy such as argument validation and output naming. The classifier only reads format descriptions. The converter owns the streaming mechanism and chooses mono or frame-packed processing from the metadata value.

Ownership and state

Ownership evidence

ProjectedMediaConversion/Converter.swift:27 — immutable converter state

final class APMPConverter: Sendable {
    let sourceVideoFrameSize: CGSize
    let reader: AVAssetReader
    let sourceVideoTrack: AVAssetReaderTrackOutput
    let sourceVideoTrackProvider:
        AVAssetReaderOutput.Provider<CMReadySampleBuffer<CMSampleBuffer.DynamicContent>>
}
Owner Object or state Relationship Mutation authority
ProjectedMediaConversion Parsed options and output URL Argument Parser populates; run derives values Mutating command instance
ProjectedMediaClassifier Classification flags and detected strings Computes immutable results in init Initializer only
APMPConverter Reader, source output, frame size, provider Creates and retains Converter initialization and conversion methods
convertToAPMP invocation Writer, input receivers, transfer session Creates as operation-local resources The active conversion task

Class and protocol design

ProjectedMediaConversion/ProjectedMediaConversion.swift:11 — framework command protocol

@main
struct ProjectedMediaConversion: AsyncParsableCommand {
    @Argument var sourceVideoPath: String
    @Flag var autoDetect = false
    mutating func run() async throws { /* ... */ }
}
Type Responsibility Depends on
ProjectedMediaConversion Parse input, validate metadata, choose destination, invoke conversion Swift Argument Parser
ProjectedMediaClassifier Interpret projection, packing, codec, and compatibility extensions AVFoundation, CoreMedia
APMPConverter Decode, split packed views when necessary, tag buffers, encode, and finish AVFoundation, VideoToolbox
ProjectedMediaMetadata Carry projection and optional stereo values Value semantics only

The only protocol-oriented boundaries are framework protocols (AsyncParsableCommand) and Sendable. The converter and classifier are concrete because the executable demonstrates one implementation.

Access control

Symbol Access Verified effect Likely rationale
All app types and members without modifiers internal by default Usable only within the executable module. No library API is intended.
APMPConverter final internal Other module types cannot subclass it; external modules cannot access it. Fixes the conversion invariant to one implementation.
Converter properties internal immutable let Module code could read them, but cannot replace them after initialization. Immutability supplies most encapsulation in this compact sample.
Operation-local writer and transfer objects lexical local scope Inaccessible after convertToAPMP returns. Ties resources to one conversion lifecycle.
convertFrame internal Any code in the target could call it. Wider than strictly necessary, likely to keep sample mechanics directly inspectable.
Explicit private / fileprivate declarations none The source relies on internal, immutable, and local scope instead. Keeps a short command-line sample easy to inspect.

Reference code

ProjectedMediaConversion/ProjectedMediaClassifier.swift:12 — module-only, immutable result object

final class ProjectedMediaClassifier {
    let convertedFromSpherical: Bool
    let isProjectedMediaProfile: Bool
    let projectionKind: String?
    let viewPackingKind: String?
}

Logic ownership and placement

Logic Owning type or file Placement rationale
Argument defaults and validation ProjectedMediaConversion CLI policy belongs at the entry boundary
Format classification ProjectedMediaClassifier Read-only interpretation is separated from mutation and output
Compression-property construction APMPConverter.convertToAPMP Coupled to writer configuration
Frame-packed eye cropping and tagging APMPConverter.convertFrame Closely coupled to source dimensions and encoding layer IDs
Output deletion and naming ProjectedMediaConversion.run User-facing command behavior rather than codec mechanics

Design patterns

Pattern Source evidence Purpose or tradeoff
Command ProjectedMediaConversion/ProjectedMediaConversion.swift:12 Gives one entry point for parsing and orchestration.
Classifier ProjectedMediaConversion/ProjectedMediaClassifier.swift:22 Isolates input inspection from conversion.
Processing pipeline ProjectedMediaConversion/Converter.swift:154, ProjectedMediaConversion/Converter.swift:164 Streams samples from provider to the correct writer receiver.
Data transfer object ProjectedMediaConversion/ProjectedMediaConversion.swift:89 Passes related metadata as one named value instead of positional parameters.
Conditional strategy without polymorphism ProjectedMediaConversion/Converter.swift:130 Selects tagged stereo versus mono receivers with a branch; simple, but not independently replaceable.

Naming conventions

  • Types describe role and output: ProjectedMediaClassifier, APMPConverter, and ProjectedMediaMetadata.
  • The executable type matches the product name.
  • Methods use outcome-oriented verbs: conformsToAPMPDeliveryVariant, convertToAPMP, and convertFrame.
  • AVFoundation and VideoToolbox constants retain framework terminology such as layer IDs, view IDs, and projection kind.

Architecture takeaways

  • Keep CLI policy separate from a streaming media pipeline.
  • Use an immutable classifier when inspection should not alter source or converter state.
  • Operation-local writer resources make conversion ownership and cleanup easy to understand.
  • A protocol abstraction is unnecessary unless the executable gains multiple converter implementations or test seams.

Source map

Source file Relevant symbols
ProjectedMediaConversion/ProjectedMediaConversion.swift ProjectedMediaConversion, ProjectedMediaMetadata, ConversionError
ProjectedMediaConversion/ProjectedMediaClassifier.swift ProjectedMediaClassifier
ProjectedMediaConversion/Converter.swift APMPConverter, MV-HEVC identifiers