Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions TRIAGE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Legend:

| Issue | Triage | Notes |
| --- | --- | --- |
| #428 | real, fixed here | Android `Video.compress` rejected with the bare `CodecException` message, which is usually empty, so every codec failure read the same. This branch appends `CodecException.diagnosticInfo` (e.g. `android.media.MediaCodec.error_neg_12` = `NO_MEMORY`) to the rejection message. |
| #423 | real, fixed here | Android `Video.compress` rejects with `NO_MEMORY` on Samsung Exynos encoders (`c2.exynos.h264.encoder`) at higher resolutions (e.g. 1080p manual mode). #399 set `KEY_PRIORITY = 0` + `KEY_OPERATING_RATE = Short.MAX_VALUE`; Exynos accepts them in `configure()` but fails `start()` ("real-time(32767 fps) is not supported"), which the `prepareEncoder` fallback doesn't cover. Small `auto` outputs (360×640) still fit the realtime budget. This branch removes both keys. Verified on a Galaxy A56 (Exynos 1580): 1080p manual fails with the keys and succeeds without them (94.1 MB → 32.0 MB). |
| #406 | real, fixed here | Nitro module not linked in Android **release** builds (works in debug). R8 strips the `HybridCompressor` implementation, which is instantiated from C++/JNI by class name (`NitroCompressorOnLoad.cpp` `kJavaDescriptor`) and was the only Nitro class lacking keep protection — the generated spec has `@DoNotStrip @Keep`, but the hand-written impl didn't. This branch annotates `HybridCompressor` with `@DoNotStrip @Keep` (the same convention nitrogen and other Nitro modules like react-native-mmkv use), so no consumer ProGuard rules are needed. Verified with a minified release build: without the annotation R8 lists the class in `usage.txt` (removed); with it, the class + no-arg constructor are kept in `mapping.txt`. |
| #404 | real, fixed here | Android Nitro module failed to compile on older React Native: the bridge `Promise.reject(...)` `code` parameter is non-null `String` on older RN but nullable `String?` on RN 0.85, and Kotlin's invariant override params can't satisfy both. This branch rewrites `NitroPromiseAdapter` in Java (nullability-erased override matching) so one implementation compiles across all RN versions. |
Expand Down Expand Up @@ -100,3 +101,4 @@ These should be closed upstream unless a current repro still exists on the lates
- Android: annotate the `HybridCompressor` impl with `@DoNotStrip @Keep` so the Nitro `Compressor` HybridObject (instantiated via JNI by name) survives R8 in consumer release builds (#406)
- Android: rewrite `NitroPromiseAdapter` in Java so the Nitro module compiles across all React Native versions regardless of `Promise.reject`'s `code` nullability (#404)
- Android: drop `KEY_PRIORITY`/`KEY_OPERATING_RATE` from the encoder format so Exynos H.264 encoders don't fail `start()` with `NO_MEMORY` (#423)
- Android: name the codec error (`CodecException.diagnosticInfo`) when video compression fails (#428)
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@ object Compressor {
// finishMovie() never runs on this path, so close the MP4Builder
// streams explicitly or the output file handle leaks.
mediaMuxer.close()
return Result(id, success = false, failureMessage = exception.message)
return Result(id, success = false, failureMessage = failureMessage(exception))
}

// Release resources
Expand Down Expand Up @@ -553,7 +553,7 @@ object Compressor {
// extractor.release) where the MP4Builder is still open. close() is
// idempotent, so calling it after a successful finishMovie() is a no-op.
muxer?.close()
return Result(id, success = false, failureMessage = exception.message)
return Result(id, success = false, failureMessage = failureMessage(exception))
}

var resultFile = cacheFile
Expand Down Expand Up @@ -773,6 +773,15 @@ object Compressor {
}
}

// A MediaCodec.CodecException often has an empty message; its diagnosticInfo
// names the codec error (e.g. android.media.MediaCodec.error_neg_12 is NO_MEMORY).
private fun failureMessage(exception: Throwable): String? =
if (exception is MediaCodec.CodecException) {
listOfNotNull(exception.message?.ifBlank { null }, exception.diagnosticInfo).joinToString(": ")
} else {
exception.message
}

// Dolby Vision profile 5 (0x20) carries no HEVC base layer, so no standard
// Android decoder can render it. Detect it up front so start() can reject the
// input before allocating the muxer/encoder/EGL surfaces. Profiles 8.x do carry
Expand Down
Loading