Skip to content

fix: reverse playback – Android HEVC rotation & AVErrorInvalidVideoComposition#138

Merged
hm21 merged 3 commits into
stablefrom
fix/reverse-playback-android-hvec-videos
May 25, 2026
Merged

fix: reverse playback – Android HEVC rotation & AVErrorInvalidVideoComposition#138
hm21 merged 3 commits into
stablefrom
fix/reverse-playback-android-hvec-videos

Conversation

@hm21
Copy link
Copy Markdown
Owner

@hm21 hm21 commented May 25, 2026

Summary

This branch fixes two bugs that caused reverse playback to fail.


1. Android – HEVC video rotation ignored during reversal

Problem: On Android, HEVC-encoded videos with a rotation metadata tag (e.g. 90°) were not correctly rotated when played in reverse. The reversed output appeared sideways or upside-down.

Fix: Applied the rotation matrix from the video's MediaFormat when writing reversed frames, so the output matches the original orientation.


2. iOS / macOS – AVErrorInvalidVideoComposition (-11841) during reverse playback

Problem: After AudioReverser was introduced, exporting a reversed clip failed with:

AVFoundationErrorDomain Code=-11841 "The video could not be composed."

Root cause: AudioReverser decodes audio to PCM at 44 100 Hz and produces a WAV file with duration PCMFrameCount / 44100. This value is typically a few microseconds longer than the video clip duration (which is quantised to the video frame timescale). Inserting the WAV into the AVMutableComposition audio track extended composition.duration beyond the coverage of the AVVideoComposition instructions, which is forbidden by AVFoundation.

Fix: Clamp the inserted WAV range to clipDuration using CMTimeMinimum in VideoSequenceBuilder.swift (both iOS and macOS):

// Clamp the WAV duration to clipDuration.
// AudioReverser produces PCM frames at 44 100 Hz, so
// reversed.duration (= PCMFrameCount/44100) is rarely
// equal to clipDuration (video frames / fps). Even a
// few microseconds of overhang extend composition.duration
// beyond the AVVideoComposition instruction coverage,
// triggering AVErrorInvalidVideoComposition (-11841).
let clampedDuration = CMTimeMinimum(reversed.duration, clipDuration)
let wavRange = CMTimeRange(start: .zero, duration: clampedDuration)
try sharedAudioTrack.insertTimeRange(wavRange, of: wavTrack, at: insertStart)

Files changed

File Change
android/…/VideoReverser.kt Apply HEVC rotation matrix during frame reversal
ios/Classes/…/AudioReverser.swift New: PCM-level audio reversal for iOS
macos/Classes/…/AudioReverser.swift New: PCM-level audio reversal for macOS
ios/Classes/…/VideoSequenceBuilder.swift Clamp reversed WAV duration to clipDuration
macos/Classes/…/VideoSequenceBuilder.swift Clamp reversed WAV duration to clipDuration
macos/Classes/…/RenderVideo.swift Remove temporary debug logging

@hm21 hm21 merged commit 959f1df into stable May 25, 2026
1 check passed
@hm21 hm21 deleted the fix/reverse-playback-android-hvec-videos branch May 25, 2026 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant