Fix AV1 videos being uploaded without transcoding, and two AV1 playback defects - #488
Merged
Conversation
nGetVideoInfo reports PARAM_NUM_SUPPORTED_VIDEO_CODEC from a hardcoded allowlist that omits AV1. PhotoViewer gates videoConvertSupported on it, so for AV1 input the whole compression setup block is skipped and the file is uploaded verbatim - no downscale, no transcode, no error.
Any MediaCodecDecoderException mentioning av1 wrote a persistent flag that was never cleared, so a single transient failure (codec exhaustion, low memory, one bad file) disabled AV1 app-wide for the life of the install. Replace it with a failure counter (threshold 3) that expires after 30 days and resets on app upgrade, and skip counting CodecException.isTransient(). Also allow software decode below 1080p for the hard gates that previously discarded the video track outright, leaving audio with a black frame.
This was referenced Jul 25, 2026
Open
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.
Fixes the AV1 send-side defect reported in #487, plus two related AV1 playback defects.
1. AV1 videos are uploaded without transcoding —
gifvideo.cppnGetVideoInforeportsPARAM_NUM_SUPPORTED_VIDEO_CODECfrom a hardcoded allowlist:AV_CODEC_ID_AV1is absent. The consequence chain:gifvideo.cppreturns 0 →PhotoViewersetsvideoConvertSupported = false→ the entire compression-setup block is skipped, soresultWidth/compressionsCount/selectedCompressionare never populated →compressItem.setState(videoConvertSupported && compressionsCount > 1, …)disables the compression UI → novideoEditedInfocarrying convert params → theSendMessagesHelpergatevideoEditedInfo != null && needConvert()fails → the original file is uploaded verbatim.It fails silently because it isn't an error path — it's a disabled feature. No error, no compression option, no indication the file went out unprocessed.
The fix adds AV1 to the allowlist, gated on API 29 where AOSP ships
c2.android.av1-dec, mirroring the existing HEVC guard. Note the convert pipeline decodes via platformMediaCodec, not the bundled FFmpeg — so nobuild_ffmpeg.shchange is required.Evidence
Device captures on a Pixel 9 Pro (Telegram 12.9.1, Android 17), logging enabled:
cache/sharing/<original>exynos.hevc.decoder+exynos.h264.encoderc2.google.av1.decoderonly — no encoder/Download/…verbatimexynos.hevc.decoder+exynos.h264.encoderRows 3 and 4 are the controlled pair — identical resolution, duration, HDR characteristics and route; only the codec differs:
For AV1, neither line appears, no encoder is created, and upload starts at
file_part=0straight from the on-disk path. The AV1 file was freshly re-encoded (different SHA256 and different decoded-frame MD5), ruling out dedup.2. One transient decoder error permanently disabled AV1 —
VideoPlayer.javaonPlayerErrorwroteunsupport_video/av01on anyMediaCodecDecoderExceptionmentioning av1, and nothing ever cleared it — no expiry, no retry, no reset on upgrade.supportsHardwareDecoder()then returned false for the life of the install, which gates thumbnails, playback, and strips AV1 URIs from the quality list. Codec-instance exhaustion from opening several videos at once is enough to trigger it, after which a device with working hardware AV1 behaves as if it had none. Only recovery was clearing app data.Replaced with a failure counter (threshold 3) that expires after 30 days and self-resets on app upgrade or when the verdict goes stale, and
CodecException.isTransient()failures aren't counted at all.3. Software decoders were never considered —
VideoPlayer.javasupportsHardwareDecoder()skipped every non-hardware-accelerated codec. Android 10+ ships a software AV1 decoder, but the method was used as a blanket gate, so on devices without hardware AV1 the video track was dropped entirely while audio kept playing — the widely reported "AV1 plays sound with a black screen". The video wasn't failing to decode; it was never being decoded.Added
supportsSoftwareDecoder()andsupportsDecoder(codec, w, h)(software permitted up to 1080p), used for the three hard gates that discarded the track.supportsHardwareDecoder()is retained for quality-selection heuristics, where preferring hardware is correct.Review notes
Things a reviewer should push on, stated rather than hidden:
triedAv1CodecFallback), reset on first-frame render and inreleasePlayer— neither is on the retry path. Below the blacklist thresholdfilterByCodecmay strip nothing, so an unbounded retry would loop forever.isCodecBlacklisted()writes SharedPreferences from what reads as a predicate (the self-healing reset). Self-limiting: only reached on a cache miss.reportCodecFailure's read-modify-write isn't atomic — concurrent failures can lose an increment. That only makes blacklisting slower, never wrong.onRenderedFirstFrame, which felt too invasive here.Also reported upstream at https://bugs.telegram.org/c/64017 (
DrKLO/Telegramhas issues disabled).