Address grill follow-ups: dead code, UUID filename, continuation guard, DataRateLimits

N1: Delete unused CodecSelector.selectEncoder. VideoCompressor calls
findEncoder directly; selectEncoder was dead since the initial commit.

N2: Switch Android output filename from System.currentTimeMillis() to
UUID.randomUUID(). Eliminates the collision risk when two compressions
start in the same millisecond.

N3: Guard CheckedContinuation against double-resume in both
processVideoTrack and processAudioTrack. AVAssetWriter shouldn't
re-invoke the requestMediaDataWhenReady block after markAsFinished, but
if it did, the previous code would crash via CheckedContinuation's
double-resume detection. Added a `finished` flag plus a local `finish`
closure that no-ops on second call.

N4: DataRateLimits window duration changed from Int `1` to Double `1.0`.
VideoToolbox expects the duration value as a CFNumber with float
semantics; Int bridges to NSNumber(int) which works on most iOS
versions but is not spec-correct.
This commit is contained in:
vineyardbovines
2026-06-18 18:06:35 -04:00
parent 434d56ad00
commit 34ee7bafda
3 changed files with 28 additions and 23 deletions
@@ -23,15 +23,6 @@ object CodecSelector {
val isHardware: Boolean
)
fun selectEncoder(preferHevc: Boolean): EncoderInfo? {
if (preferHevc) {
val hevc = findEncoder(MediaFormat.MIMETYPE_VIDEO_HEVC, requireHardware = true)
if (hevc != null) return hevc
}
findEncoder(MediaFormat.MIMETYPE_VIDEO_AVC, requireHardware = true)?.let { return it }
return findEncoder(MediaFormat.MIMETYPE_VIDEO_AVC, requireHardware = false)
}
fun findEncoder(mime: String, requireHardware: Boolean): EncoderInfo? {
val codecList = MediaCodecList(MediaCodecList.REGULAR_CODECS)
val candidates = codecList.codecInfos
@@ -11,6 +11,7 @@ import android.os.Build
import android.util.Log
import java.io.File
import java.nio.ByteBuffer
import java.util.UUID
class VideoCompressor(
private val context: Context,
@@ -72,7 +73,7 @@ class VideoCompressor(
encoderInfo: CodecSelector.EncoderInfo,
useHevc: Boolean
): Map<String, Any> {
val outputFile = File(context.cacheDir, "${System.currentTimeMillis()}.mp4")
val outputFile = File(context.cacheDir, "${UUID.randomUUID()}.mp4")
var extractor: MediaExtractor? = null
var muxer: MediaMuxer? = null