Skip to main content

Module Overview

The LCK SDK is organized into modular runtime modules with specific loading phases:
LCKVulkan (EarliestPossible)
    |
LCKCore (PostDefault)
    ├── LCKAudio (PostDefault)
    ├── LCKWindowsEncoder (Win64 only)
    ├── LCKAndroidEncoder (Android only)
    └── LCKAndroidGallery (Android only)

Core Architecture

┌─────────────────────────────────────────────────────────┐
│                    UWorld                                │
├─────────────────────────────────────────────────────────┤
│  ULCKRecorderSubsystem (TickableWorldSubsystem)         │
│  └── ILCKEncoder (Platform-specific implementation)     │
├─────────────────────────────────────────────────────────┤
│  ULCKSubsystem (WorldSubsystem)                         │
│  └── ULCKService (Recording, Camera Control)            │
├─────────────────────────────────────────────────────────┤
│  ALCKTablet (Actor)                                      │
│  └── ULCKTabletDataModel (State Management)             │
└─────────────────────────────────────────────────────────┘

Subsystem Hierarchy

Type: UTickableWorldSubsystem Module: LCKCoreThe low-level recording subsystem that manages encoder lifecycle and frame capture.
UCLASS()
class LCKCORE_API ULCKRecorderSubsystem : public UTickableWorldSubsystem
{
    // Recording Control
    void SetupRecorder(const FLCKRecorderParams& Params,
                      USceneCaptureComponent2D* CaptureComponent);
    void StartRecording();
    void StopRecording();
    void StartRecordingAsync(FOnLCKRecorderBoolResult Callback);
    void StopRecordingAsync(FOnLCKRecorderBoolResult Callback,
                           FOnLCKRecorderProgress ProgressCallback);

    // Preview Mode
    void StartPreview();
    void StopPreview();

    // Photo Capture
    void TakePhoto();

    // State Queries
    bool IsRecording() const;
    float GetTime() const;
    float GetMicrophoneVolume() const;
};

Encoder Architecture

ILCKEncoder Interface

Abstract encoder interface implemented by platform-specific modules:
class ILCKEncoder : public FRunnable
{
public:
    virtual bool Open() = 0;
    virtual bool IsEncoding() const = 0;
    virtual void EncodeTexture(FTextureRHIRef& Texture, float TimeSeconds) = 0;
    virtual void EncodeAudio(TArrayView<float> PCMData) = 0;
    virtual void Save(TFunction<void(float)> ProgressCallback) = 0;
    virtual float GetAudioTime() const = 0;
};

ILCKEncoderFactory

Factory interface for creating platform-specific encoders:
class ILCKEncoderFactory : public IModularFeature
{
public:
    static FName GetModularFeatureName() { return TEXT("LCKEncoderFactory"); }

    virtual FString GetEncoderName() const = 0;
    virtual TSharedPtr<ILCKEncoder> CreateEncoder(
        int32 Width, int32 Height, int32 VideoBitrate,
        int32 Framerate, int32 Samplerate, int32 AudioBitrate) = 0;
};

Platform Implementations

Windows Encoder

  • Windows Media Foundation (IMFSinkWriter, IMFTransform)
  • H.264 video, AAC audio
  • MP4 container output
  • Triple-buffered texture pool

Android Encoder

  • Android NDK MediaCodec
  • Vulkan texture interop via EGL
  • Hardware-accelerated encoding
  • Google Oboe for audio capture

Audio Architecture

ILCKAudioSource Interface

Modular audio source interface for extensible audio capture:
class ILCKAudioSource : public IModularFeature,
                        public TSharedFromThis<ILCKAudioSource>
{
public:
    static FName GetModularFeatureName() { return TEXT("LCKAudioSource"); }

    // Single delegate (not multicast) - use BindLambda
    FOnRenderAudioDelegate OnAudioDataDelegate;

    // Control methods
    virtual bool StartCapture() noexcept = 0;
    virtual bool StartCapture(TLCKAudioChannelsMask Channels) noexcept = 0;
    virtual void StopCapture() noexcept = 0;

    // Query methods
    virtual float GetVolume() const noexcept = 0;
    virtual const FString& GetSourceName() const noexcept = 0;
    TLCKAudioChannelsMask GetSupportedChannels() const noexcept;

protected:
    TLCKAudioChannelsMask SupportedChannels;
};

FLCKAudioMix

Audio mixing utility for combining multiple sources:
class FLCKAudioMix
{
public:
    void AddSource(TSharedPtr<ILCKAudioSource> Source);
    void RemoveSource(TSharedPtr<ILCKAudioSource> Source);

    // Get mixed stereo audio for specified channels
    TArray<float> StereoMix(TLCKAudioChannelsMask Channels);

private:
    TArray<TWeakPtr<ILCKAudioSource>> Sources;
    FCriticalSection Mutex;
};

Data Flow

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Scene Capture  │────>│  Render Target  │────>│                 │
└─────────────────┘     └─────────────────┘     │                 │
                                                │  Encoder Thread │────> MP4 File
┌─────────────────┐     ┌─────────────────┐     │                 │
│  Audio Sources  │────>│   Audio Mix     │────>│                 │
└─────────────────┘     └─────────────────┘     └─────────────────┘

Thread Safety

The SDK uses standard Unreal Engine thread-safety patterns:
MechanismUsage
FCriticalSectionMutex protection for shared data
FRunnableThreadEncoding worker threads
Queue-based communicationThread-safe message passing
Atomic operationsState flags
Audio callbacks may come from different threads. Use AsyncTask(ENamedThreads::GameThread, ...) if you need to access game thread objects from audio callbacks.

Modular Feature Discovery

The SDK uses Unreal’s modular features system for extensibility:
// Find default encoder factory
ILCKEncoderFactory* Factory = nullptr;
auto& ModularFeatures = IModularFeatures::Get();
if (ModularFeatures.IsModularFeatureAvailable(ILCKEncoderFactory::GetModularFeatureName()))
{
    Factory = &ModularFeatures.GetModularFeature<ILCKEncoderFactory>(
        ILCKEncoderFactory::GetModularFeatureName());
}

// Find all audio sources
TArray<ILCKAudioSource*> AudioSources =
    ModularFeatures.GetModularFeatureImplementations<ILCKAudioSource>(
        ILCKAudioSource::GetModularFeatureName());

Log Categories

CategoryDescription
LogLCKCore SDK operations
LogLCKEncodingVideo/audio encoding
LogLCKAudioAudio capture and mixing
LogLCKUIUI component operations
LogLCKTabletTablet-specific operations
Enable verbose logging in DefaultEngine.ini:
[Core.Log]
LogLCK=VeryVerbose
LogLCKEncoding=VeryVerbose
LogLCKAudio=VeryVerbose
LogLCKUI=Verbose
LogLCKTablet=Verbose