{"record":{"id":"ea41e3ac94aae553","repo":"stride3d/stride","slug":"avfoundationvideobackend-already-initialized","errorCode":null,"errorMessage":"AVFoundationVideoBackend already initialized.","messagePattern":"AVFoundationVideoBackend already initialized\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Video/Backends/AVFoundationVideoBackend.cs","lineNumber":58,"sourceCode":"    private int videoWidth;\n    private int videoHeight;\n    private TimeSpan frameDuration;\n    private long adjustedTicksSinceLastFrame;\n\n    // Audio runs on the StreamedBufferSoundSource worker thread; video clock forwards to the synchronizer.\n    private MediaSynchronizer audioSynchronizer;\n    private StreamedBufferSound audioSound;\n    private SoundInstanceStreamedBuffer audioSoundInstance;\n    private readonly System.Collections.Generic.List<AudioEmitterSoundController> audioControllers = new();\n\n    public AVFoundationVideoBackend(VideoInstance instance) : base(instance) { }\n\n    public override bool UsesHardwareDecode => true; // AVAssetReader uses VideoToolbox\n\n    public override bool Initialize(string url, long startPosition, long length)\n    {\n        if (reader != null)\n            throw new InvalidOperationException(\"AVFoundationVideoBackend already initialized.\");\n\n        try\n        {\n            tempFilePath = ExtractAssetSliceToTempFile(url, startPosition, length);\n\n            using var assetUrl = NSUrl.FromFilename(tempFilePath);\n            asset = AVAsset.FromUrl(assetUrl);\n\n            var videoTracks = asset.TracksWithMediaType(AVMediaTypes.Video.GetConstant());\n            if (videoTracks == null || videoTracks.Length == 0)\n            {\n                VideoInstance.Logger.Warning(\"AVFoundationVideoBackend: media has no video track.\");\n                ReleaseMedia();\n                return false;\n            }\n            videoTrack = videoTracks[0];\n\n            var size = videoTrack.NaturalSize;","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Video/Backends/AVFoundationVideoBackend.cs#L40-L76","documentation":"AVFoundationVideoBackend.Initialize was called on a backend instance that is already initialized and holds a live AVAssetReader (reader != null). The backend does not support re-initialization while active; it must be disposed or reset first.","triggerScenarios":"Calling Initialize twice on the same backend instance without Dispose/Reset in between; a video component re-assigning the same URL to an already-playing instance; lifecycle code that reuses backends across Play calls.","commonSituations":"Replaying the same video through a cached backend object; hot-reload or scene restart code re-initializing the shared backend; forgetting to call Dispose when switching videos.","solutions":["Dispose (or reset) the backend before calling Initialize again","Create a new AVFoundationVideoBackend instance for each video/URL","In the caller, guard re-initialization: skip if already initialized with the same URL","Check the video component's lifecycle so each play cycle gets a fresh backend"],"exampleFix":"// before\nbackend.Initialize(url, start, length);\nbackend.Initialize(url, start, length); // throws\n// after\nif (backend.ReaderActive) backend.Dispose();\nbackend.Initialize(url, start, length);","handlingStrategy":"validation","validationCode":"if (backend.IsInitialized) backend.Dispose();\nbackend.Initialize(url, startPosition, length);","typeGuard":"bool CanInitialize(AVFoundationVideoBackend b) => !b.IsInitialized;","tryCatchPattern":"try { backend.Initialize(url, start, len); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"already initialized\"))\n{ backend.Dispose(); backend.Initialize(url, start, len); }","preventionTips":["One backend instance per video session; recreate rather than re-init","Track backend lifecycle state in the owning component","Always Dispose on scene/component teardown"],"tags":["ios","avfoundation","video","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}