Repository navigation
V1.0.0
First release on pub.dev.
- iOS/macOS: a writer whose encoder stops accepting frames now fails with
encoderStalledafter 5 seconds (or 60 seconds to finish the file)
instead of hanging forever, like Android. - The example app now picks a video, applies a filter to every frame,
exports it with the original sound and plays it. CI runs on GitHub Actions.
The README has install steps, a before/after image, a comparison with
other options, and error-code and memory tables. - macOS support (12+). iOS and macOS share one Swift implementation
(sharedDarwinSource), which moved fromios/todarwin/. - A writer whose
finish()fails now frees the encoder and deletes the broken
file (Android leaked the hardware encoder; both platforms left the file).
An Android writer that fails while being created no longer leaks it either. - Android: a stuck encoder now fails with "video encoder stalled" after 5
seconds instead of hangingaddFrameorfinishforever. - iOS: a frame whose pixel memory can't be read or allocated now returns an
error to Dart instead of crashing the app. - Readers and writers that are never closed are freed when garbage-collected
(a forgotten writer is cancelled). iOS now frees everything when the
Flutter engine shuts down, as Android already did. - Faster frame conversion. Android now decodes and encodes through OpenGL ES
(the GPU converts, rotates and scales), about 3x faster at 1080p on an
emulator; iOS uses Accelerate (vImage) for full-size frames. - Android: the first
frameAton a reader no longer sometimes fails with
"video decoder stalled". - Written videos are tagged BT.709 (both platforms). Players no longer guess
the color space, which shifted greens and skin tones in HD output. VideoReader.open(..., filter:)chooses howmaxDimensionscales frames:
ScaleFilter.nearest(default),bilinearorarea.frameAtnow scales
exactly likenextFrameon iOS. Nearest sampling picks the pixel at each
output pixel's center on both platforms (iOS used to pick its top-left).- Breaking: the host API is split into
VideoReaderHostApiand
VideoWriterHostApi, each on its own native queue, so decoding can overlap
encoding (see the pipelined loop in the README). The test seam
VideoFrames.apiis replaced byVideoFrames.readerApiand
VideoFrames.writerApi. VideoWriter.create(..., codec: VideoCodec.hevc)writes HEVC; it fails
with a clear error on devices without an HEVC encoder.- HDR input: iOS
frameAtnow decodes withAVAssetReaderlikenextFrame,
so HDR frames get the same tone mapping (the image generator path was
darker and differently colored). Android 13+ asks decoders to tone-map
HDR to SDR, plays Dolby Vision 8/9 (e.g. iPhone videos) through the HEVC/AVC
base layer when there is no Dolby Vision decoder, and picks a decoder that
supports the track's profile (e.g. 10-bit) instead of the default one. - Less copying per frame: Android reads GPU pixels straight into one reused
buffer per decoder instead of allocating a new array (plus a copy) per
frame; iOS builds frames asData, dropping a full-frame copy in the
plugin. The README has a per-resolution memory table. - Android: a decoder that fails mid-stream now reports which codec and video
it was ("c2.x.hevc.decoder (video/hevc 640x360) can't decode this video")
instead of only "Invalid to call at Released state". - Android: the HDR-to-SDR tone-mapping request is only sent for HDR video.
On SDR video it made Qualcomm decoders fail ("not a supported pixel
format"), so videos the plugin itself wrote couldn't be read on those
phones. - Android: encoders and decoders are tried in the device's preference order
until one starts, ending with Android's software codecs. Vendor codecs can
claim a format and still fail to start (Qualcomm's H.264 encoder at 64x64
and 256x64); those sizes now fall back instead of failing. - Breaking: the generated host API and message types
(VideoReaderHostApi,VideoWriterHostApi,VideoFrameMessage,
VideoInfoMessage) moved frompackage:video_frames/video_frames.dartto
package:video_frames/testing.dart, andVideoFrames.readerApi/
writerApiare@visibleForTesting. Every public member is documented. - Breaking: failures throw
VideoFramesExceptionwith a
VideoFramesErrorCode(fileNotFound,unsupportedFormat,
codecUnsupported,encoderStalled,readFailed,writeFailed,
unknown) instead of a rawPlatformException.