feat(reader): replace MP4 transcoding with CADisplayLink-driven animated image player#623
Merged
feat(reader): replace MP4 transcoding with CADisplayLink-driven animated image player#623
Conversation
…ted image player Animated GIF/WebP pages in the DIVINA reader were transcoded to MP4 via AVAssetWriter before playback, which was slow. Replace the entire transcode pipeline with a CADisplayLink-driven frame decoder that reads frames lazily from CGImageSource, eliminating the conversion step entirely. New files: - AnimatedImageFrameDecoder: parses GIF/WebP frame durations, decodes individual frames on demand - AnimatedImagePlayerController: drives playback via CADisplayLink with a ring buffer of ~5 pre-decoded frames and automatic eviction - AnimatedImagePlayerView: SwiftUI wrapper (UIViewRepresentable on iOS, NSViewRepresentable on macOS, disabled on tvOS) Removed: - AnimatedImageVideoTranscoder (MP4 transcode pipeline) - LoopingVideoPlayerView (AVQueuePlayer-based playback) Simplified ReaderViewModel, ReaderViewItemImageView, and NativeImagePageViewController by removing all transcoder references, progress tracking, and preparation task management.
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.
Problem
The DIVINA reader transcodes animated GIF/WebP images to MP4 via
AVAssetWriter(frame-by-frame decode → CVPixelBuffer → H.264) before playback withAVQueuePlayer. This transcode step is slow and adds visible loading time with a progress indicator before animated pages can play.Approach
Replace the entire transcode-then-play pipeline with a
CADisplayLink-driven approach that decodes frames lazily fromCGImageSource:AnimatedImageFrameDecoderowns aCGImageSourceand provides frame count, per-frame duration (reusing the exact GIF/WebP unclamped/clamped delay logic), and on-demand single-frame decodingAnimatedImagePlayerControllerdrives aCADisplayLink, maintains a ring buffer of ~5 pre-decodedCGImageframes, advances frames based on accumulated elapsed time, and setsCALayer.contentsdirectlyCADisplayLink(target:selector:)on iOS,NSScreen.displayLink(target:selector:)on macOSScope
AnimatedImageFrameDecoder,AnimatedImagePlayerController,AnimatedImagePlayerViewReaderViewModel(removed transcoder state, preparation tasks, progress tracking),ReaderViewItemImageView(removed progress overlay and monitoring loop),NativeImagePageViewController(replaced AVPlayer stack with controller)AnimatedImageVideoTranscoder,LoopingVideoPlayerViewValidation
make buildpasses on all three platforms (iOS, macOS, tvOS)