dart_vp8 0.3.0 copy "dart_vp8: ^0.3.0" to clipboard
dart_vp8: ^0.3.0 copied to clipboard

Pure-Dart VP8 video codec (RFC 6386). Byte-exact decoder on all 62 official VP8 conformance vectors, plus an experimental VP8 encoder. IVF + WebM demuxers, IVF + WebM writers; no native code, no dart: [...]

dart_vp8 #

Pure-Dart VP8 video codec (RFC 6386). Correctness-focused reference port of the upstream libvpx. No SIMD, no platform plugins, no dart:io dependency in the library.

Status #

Component Status
Decoder Stable. Byte-exact on all 62 official conformance vectors
IVF + WebM demuxers Stable; auto-detect, Cues seeking, streaming WebM reader
WebM + IVF writers Stable
Encoder (encoder.dart) Experimental. Conformant bitstream; RD pipeline evolving

Decoder conformance #

All 62 official VP8 conformance vectors from libvpx's kVP8TestVectors list decode byte-exact against the upstream reference (MD5 of the raw I420 output, every frame, every vector):

Suite Vectors Status
vp80-00-comprehensive 18 ✔ pass
vp80-01-intra 4 ✔ pass
vp80-02-inter 4 ✔ pass
vp80-03-segmentation 22 ✔ pass
vp80-04-partitions 3 ✔ pass
vp80-05-sharpness 10 ✔ pass
vp80-06-smallsize 1 ✔ pass
Total 62 ✔ pass

Plus 14 robustness tests covering malformed / truncated / corrupt input.

Features #

  • Pure Dart, zero runtime dependencies.
  • Decodes any conforming VP8 stream: key + inter frames, all four MV partitionings (16x16, 16x8, 8x16, 4x4 SPLITMV), B_PRED intra, multi- token-partition (1 / 2 / 4 / 8), full segmentation with per-segment Q / LF deltas, normal + simple loop filter at all sharpness levels, hidden reference frames (show_frame=0).
  • Minimal IVF demuxer + writer, a WebM/Matroska demuxer (V_VP8 video tracks) with Cues-based seeking, a streaming WebM reader for chunked input, and a WebmWriter for muxing raw VP8 frames into .webm files. Use Vp8Reader to auto-detect IVF or WebM.
  • Library imports only dart:typed_data — runs on the VM, AOT, and Flutter Web.

Install #

dependencies:
  dart_vp8: ^0.3.0

Decoding #

import 'dart:io';
import 'dart:typed_data';

import 'package:dart_vp8/dart_vp8.dart';

void main(List<String> args) {
  final bytes = Uint8List.fromList(File(args.single).readAsBytesSync());
  // Auto-detects IVF (.ivf) or WebM (.webm) from the magic bytes.
  final reader = Vp8Reader(bytes);
  final decoder = Vp8Decoder();

  while (true) {
    final pkt = reader.nextPacket();
    if (pkt == null) break;
    final out = decoder.decodeBytes(pkt.data);
    if (!out.isShown) continue; // hidden / alt-ref reference

    // out.y, out.u, out.v are Uint8List planes at strides
    // out.yStride and out.uvStride. Crop to out.width x out.height.
    print('${out.width}x${out.height} '
        '(${out.isKeyFrame ? "kf" : "inter"})');
  }
}

The returned Uint8List planes alias the decoder's internal buffers and are overwritten on the next decode() call; copy them out if you need to keep them around.

Encoding (experimental) #

The encoder lives behind a separate import so it doesn't pull into decoder-only builds and so the experimental status is explicit:

import 'dart:io';
import 'dart:typed_data';

import 'package:dart_vp8/encoder.dart';

void main() {
  const w = 176, h = 144;
  final enc = Vp8Encoder(width: w, height: h, qi: 30,
      keyframeInterval: 30);
  final ivf = IvfWriter(width: w, height: h,
      timebaseNumerator: 1, timebaseDenominator: 30);

  for (var i = 0; i < numFrames; i++) {
    final f = enc.encodeFrame(
      srcY: yPlane, srcU: uPlane, srcV: vPlane,
      srcYStride: w, srcUvStride: w ~/ 2,
      forceKey: i == 0,
    );
    if (!f.isDropped) ivf.addFrame(f.bytes, pts: i);
  }
  File('out.ivf').writeAsBytesSync(ivf.finish());
}

The bitstream is RFC 6386 conformant — Vp8Decoder (and any other compliant decoder, including libvpx's vpxdec) decodes the output byte-exactly. Rate/quality tradeoffs continue to improve in minor releases; the public encoder surface is intended to stay stable while internals churn.

What the encoder ships with today: keyframe-interval scheduling, CBR rate control with frame drops, integer + sub-pel motion search (NEAREST/NEAR/NEW), GOLDEN/ALTREF reference handling, multi-token- partition output, auto loop-filter, ROI Q-delta, activity-AQ, temporal denoiser, cyclic refresh, static-MB short-circuit, and optional RD-based intra/inter mode decision.

API surface #

Decoder side — package:dart_vp8/dart_vp8.dart:

  • Vp8Reader / Vp8Packet — container-agnostic demuxer (IVF or WebM).
  • IvfReader / IvfFrame — IVF-only demuxer.
  • WebmReader / WebmFrame / WebmTrack — WebM/Matroska V_VP8 demuxer with seekToTime.
  • WebmStreamReader — incremental WebM reader for chunked input.
  • WebmWriter — mux a sequence of VP8 frames into a .webm file.
  • Vp8Decoder — stateful decoder; one instance per stream.
  • DecodedFrame — decoded I420 output (Y, U, V planes + metadata).

Encoder side — package:dart_vp8/encoder.dart:

  • Vp8Encoder — stateful encoder; one instance per stream.
  • EncodedVp8Frame — encoded bitstream + reconstructed I420 + stats.
  • Vp8FrameStats / Vp8CumulativeStats — per-frame and aggregate encoder telemetry.
  • IvfWriter — minimal IVF muxer.
  • CbrRateController — pluggable constant-bitrate rate controller.
  • TemporalDenoiser — optional pre-encode denoiser.

Lower-level primitives (boolean coder, frame header parser, IDCT/FDCT, intra/inter predictors, loop filter, etc.) are exported from the decoder library so they can be exercised in isolation by tests; most callers do not need them.

Testing #

dart test                                  # full suite
dart test test/conformance_suite_test.dart # 62 conformance vectors
dart test test/robustness_test.dart        # malformed-input fuzz

The 62 conformance .ivf / .ivf.md5 fixtures live under test/fixtures/. Fetch them with:

bash tool/fetch_vectors.sh

(downloads ~3 MB from storage.googleapis.com/downloads.webmproject.org/test_data/libvpx).

Benchmarking #

Decoder throughput:

dart compile exe bin/bench.dart -o bin/bench.exe
./bin/bench.exe test/fixtures/vp80-00-comprehensive-014.ivf 20

Indicative AOT throughput on a single core (dart compile exe):

Vector Resolution FPS
vp80-00-comprehensive-013 (small) 176x144 ~1500
vp80-01-intra-1411 (intra-only) 320x240 ~600
vp80-00-comprehensive-014 (SPLITMV-rich) 176x144 ~575

This is a correctness reference, not a production codec — expect a hardware decoder or libvpx itself to be roughly an order of magnitude faster.

An in-tree encoder vs libvpx harness (Y4M in → PSNR/bytes table out) lives under tool/bench/ in the repository; it is not shipped with the package.

Non-goals #

  • VP9 / AV1 decoders.
  • MP4 demuxer (use a separate package — WebM is supported in-tree).
  • Audio decoding (Vorbis / Opus). The WebM demuxer ignores audio tracks.
  • Hardware acceleration / SIMD.
  • Real-time playback guarantees.

License #

BSD-3-Clause, matching upstream libvpx. The reference C source this project ports from is libvpx (https://chromium.googlesource.com/webm/libvpx), copyright the WebM project authors.

0
likes
120
points
36
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Pure-Dart VP8 video codec (RFC 6386). Byte-exact decoder on all 62 official VP8 conformance vectors, plus an experimental VP8 encoder. IVF + WebM demuxers, IVF + WebM writers; no native code, no dart:io in the library — runs on VM, AOT and Web.

Repository (GitHub)
View/report issues

Topics

#vp8 #video #codec #webm #encoder

License

BSD-3-Clause (license)

More

Packages that depend on dart_vp8