Skip to content

fix(video): Dolby Vision crash, 50% faster transcode, fps/bitrate/GPS fixes#399

Open
HuuNguyen312 wants to merge 4 commits into
numandev1:mainfrom
HuuNguyen312:main
Open

fix(video): Dolby Vision crash, 50% faster transcode, fps/bitrate/GPS fixes#399
HuuNguyen312 wants to merge 4 commits into
numandev1:mainfrom
HuuNguyen312:main

Conversation

@HuuNguyen312
Copy link
Copy Markdown

@HuuNguyen312 HuuNguyen312 commented May 14, 2026

Summary

Bug (#398) — Dolby Vision crash on .MOV from iPhone:
createDecoderByType("video/dolby-vision") throws on Android — no standalone DV decoder. DV profile 8.x has HEVC base layer, so remap mime → video/hevc. Reject profile 5 (0x20) explicitly (no HEVC fallback).

Perf (#384) — ~50% faster transcode:

  • HW AVC encoder via MediaCodecList(ALL_CODECS), blacklist c2.qti.avc.encoder (corrupt MP4).
  • Feed decoder until input slots drain (parallel decode-render-encode).
  • Drop frames only when source fps > target fps; anchor next slot to ideal grid, not actual PTS.
  • Encoder: VBR + KEY_PRIORITY=0 + KEY_OPERATING_RATE=MAX.
  • SurfaceTexture.onFrameAvailable on dedicated HandlerThread.
  • Skip StreamableVideo rewrite when no streamableFile passed.

fps detection:

  • Derive source fps from frame_count / duration when CAPTURE_FRAMERATE absent (most non-slo-mo clips returned 0, forced 30fps cap).
  • Raise fps cap 30 → 60 on Android + iOS.

Bitrate:

  • WhatsApp-style envelope (~1.5 Mbps @ 720p). Previous bands produced 20-40 MB for short clips. Android + iOS in sync.

GPS preservation:

  • LocationExtractor walks raw MP4 box tree: handles ©xyz, ISO loci, iTunes meta/keys+ilst, Samsung SEF trailer regex.
  • MediaMetadataRetriever misses vendor-specific placements; extractor covers the gaps.
  • iOS: forward asset.metadata + all availableMetadataFormats to AVAssetExportSession.

Stability:

  • dispose() wraps every step in runCatching — teardown failure no longer leaks codec handles.
  • OutputSurface.release() joins HandlerThread after quitSafely() — prevents SIGABRT on stale pthread_t.

Changelog

[ANDROID] [FIXED] Dolby Vision .MOV no longer crashes (#398)
[ANDROID] [CHANGED] Transcode pipeline ~50% faster (#384)
[ANDROID] [FIXED] Source fps derived from frame count when CAPTURE_FRAMERATE absent
[ANDROID] [FIXED] GPS metadata preserved via raw MP4 box walker + Samsung SEF scan
[iOS] [FIXED] fps cap raised to 60; bitrate bands halved; source metadata forwarded
[ANDROID] [FIXED] Codec teardown wrapped in runCatching; OutputSurface thread joined


Test Plan

  • yarn test:pr
  • yarn test:harness:android
  • iPhone HDR .MOV (DV profile 8.4) — was crash, now transcodes
  • 500MB MP4: ~60s → ~30s on Android
  • Output MP4 plays on macOS QuickTime + iOS Photos
  • 60fps source output stays 60fps (not halved to 30fps)
  • Output file retains GPS coordinates from source
  • yarn test:harness:ios

HuuNguyen312 and others added 3 commits May 14, 2026 10:04
  iPhone HDR .MOV uses video/dolby-vision mime which has no
  standalone Android decoder, so createDecoderByType throws
  "Failed to initialize video/dolby-vision". DV profiles 8.x
  carry an HEVC base layer, so remap mime to video/hevc before
  configuring the decoder. Reject profile 5 (0x20) explicitly
  since it has no HEVC fallback.

  Perf, bundled to land with the codec rework:
  - Pick HW AVC encoder via MediaCodecList(ALL_CODECS), blacklist
    c2.qti.avc.encoder (corrupt MP4 on Mac/iOS).
  - Feed decoder until input slots drain instead of one sample
    per loop; unblocks parallel decode-render-encode.
  - Drop decoded frames whose PTS precedes the next target slot
    when source fps exceeds output fps.
  - Encoder: VBR + KEY_PRIORITY=0 + KEY_OPERATING_RATE=MAX to
    unthrottle HW codec scheduling.
  - Route SurfaceTexture onFrameAvailable to a dedicated
    HandlerThread so awaitNewImage stops contending with the
    main/JS thread.
  - Skip StreamableVideo rewrite unless caller passed a
    streamableFile; halves disk I/O for chat uploads.
Android: extract METADATA_KEY_LOCATION and write an Apple-style "©xyz"
udta atom into the muxed MP4 so geotags survive transcoding.
iOS: forward asset.metadata plus every available metadata format to the
AVAssetExportSession so location, creation date, and other tags are
retained in the exported file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- fps: derive from frame_count/duration when CAPTURE_FRAMERATE absent.
  Cap 30→60. Drop-gate only when source>target, anchor to ideal grid.
- bitrate: WhatsApp envelope (~1.5 Mbps @ 720p). Android+iOS sync.
- GPS: LocationExtractor walks MP4 — ©xyz, loci, iTunes meta/keys+ilst,
  SEF trailer regex. Writer ©xyz moved to LocationBox class.
- teardown: runCatching every dispose step. join() OutputSurface thread
  after quitSafely to avoid SIGABRT on stale pthread_t.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@HuuNguyen312 HuuNguyen312 changed the title fix(android): support Dolby Vision MOV and speed up transcode fix(video): Dolby Vision crash, 50% faster transcode, fps/bitrate/GPS fixes May 15, 2026
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