# `MobMedia.Engine.Native`
[🔗](https://github.com/GenericJam/mob_media/blob/0.1.0/lib/mob_media/engine/native.ex#L1)

The platform decoders, through the `:mob_media_nif` NIF linked into the app
by its native build.

  * Android: the C NIF hands each job to the Kotlin `MobMediaBridge`, which
    runs it on its own two-thread pool: `MediaExtractor` + `MediaCodec` for
    PCM (downmixed and resampled in Kotlin, the same algorithm as
    `MobMedia.PCM`), `MediaExtractor` + `MediaMetadataRetriever` for info,
    `MediaMetadataRetriever.getScaledFrameAtTime` for frames.
  * iOS: the Objective-C NIF runs each job on an `NSOperationQueue` (two at a time):
    `AVAssetReader` with LinearPCM output settings at the requested rate
    and channels (Core Audio does the conversion), `AVAssetImageGenerator`
    for frames, `AVURLAsset` for info.

No BEAM scheduler (normal or dirty) runs any decoding; a Mob app has one
dirty CPU and one dirty IO scheduler and they're not ours to hold.

Synchronous errors on Android are `{:error, {:jni, reason}}`: `:no_jenv`,
`:bridge_not_registered` (`MobMediaBridge.register()` didn't run before the
BEAM started), `:alloc` or `:call_failed` (the bridge threw; it logs why
under the `MobMedia` logcat tag). On iOS the only one is `{:error, :alloc}`
(the job couldn't be allocated).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
