====== std.video — Video-Metadaten ======
Das ''std.video''-Paket liest Video-Container-Metadaten (Auflösung, Dauer, FPS, Codec) aus AVI- und MP4/ISOBMFF-Dateien. AVI-Dateien mit MJPEG-Codec unterstützen zusätzlich Frame-Extraktion und Dekodierung.
Es gibt **kein** vollständiges Videodecoding (keine Softdecoder für H.264/H.265/AV1) — die Units sind auf Metadaten-Extraktion und MJPEG-Einzelbilder ausgelegt.
→ [[lyx_-_programmiersprache:units|Units-Übersicht]] · [[lyx_-_programmiersprache:start|Lyx-Sprache]]
----
===== Units =====
^ Unit ^ Code ^ Beschreibung ^
| ''std.video.core'' | VID-00 | ''VidMeta''-Struct, Format- und Codec-Konstanten, Container-Erkennung |
| ''std.video.avi'' | VID-01 | AVI-Reader: Metadaten, Frame-Zählung, MJPEG-Frame-Extraktion |
| ''std.video.mp4'' | VID-02 | MP4/ISOBMFF-Reader: Box-Traversierung, Video-Track-Metadaten, Codec-Erkennung |
----
===== VidMeta-Struct =====
''VidMeta'' ist ein 64-Byte-Puffer im Heap. Alle Felder sind ''int64'' (8 Bytes). Die Funktionen ''AviMeta'', ''AviMetaFile'', ''Mp4Meta'' und ''Mp4MetaFile'' schreiben direkt in diesen Puffer:
^ Konstante ^ Offset ^ Inhalt ^
| ''VID_OFF_WIDTH'' | 0 | Videobreite in Pixeln |
| ''VID_OFF_HEIGHT'' | 8 | Videohöhe in Pixeln |
| ''VID_OFF_DURATION_MS'' | 16 | Gesamtdauer in Millisekunden |
| ''VID_OFF_FPS_NUM'' | 24 | FPS-Zähler (Frames per Second, Zähler) |
| ''VID_OFF_FPS_DEN'' | 32 | FPS-Nenner |
| ''VID_OFF_FRAME_COUNT'' | 40 | Gesamtzahl der Frames |
| ''VID_OFF_FORMAT'' | 48 | Container-Format (''VID_FMT_*'') |
| ''VID_OFF_CODEC'' | 56 | Codec (''VID_CODEC_*'') |
| ''VID_SIZE'' | 64 | Gesamtgröße des Structs |
FPS wird als Bruch dargestellt: ''FPS = VID_OFF_FPS_NUM / VID_OFF_FPS_DEN''. Bei MP4 sind beide Felder nicht aus dem ''moov''-Box ableitbar und werden auf 0/1 gesetzt.
----
===== Konstanten =====
==== Container-Formate ====
^ Konstante ^ Wert ^ Format ^ Erkennungsmerkmal ^
| ''VID_FMT_UNKNOWN'' | 0 | Unbekannt | — |
| ''VID_FMT_AVI'' | 1 | AVI | ''RIFF'' + ''AVI '' ab Offset 8 |
| ''VID_FMT_MP4'' | 2 | MP4/ISOBMFF | ''ftyp'' ab Offset 4 |
==== Codecs ====
^ Konstante ^ Wert ^ Codec ^ Typische Verwendung ^
| ''VID_CODEC_UNKNOWN'' | 0 | Unbekannt | — |
| ''VID_CODEC_MJPEG'' | 1 | Motion JPEG | Überwachungskameras, Screencasts |
| ''VID_CODEC_H264'' | 2 | H.264 / AVC | Standard-Web- und Kameravideo |
| ''VID_CODEC_H265'' | 3 | H.265 / HEVC | 4K, effizientere Kompression |
| ''VID_CODEC_AV1'' | 4 | AV1 | Streaming, lizenzfrei |
| ''VID_CODEC_MP4V'' | 5 | MPEG-4 Part 2 | Ältere Kameras, DivX/Xvid |
| ''VID_CODEC_VP8'' | 6 | VP8 | WebM, ältere Browser |
| ''VID_CODEC_VP9'' | 7 | VP9 | YouTube, Chrome |
----
===== Quickstart =====
import std.video.core;
import std.video.mp4;
import std.alloc;
import std.io;
fn main(): int64 {
var vid: int64 := alloc(VID_SIZE);
var ok: int64 := Mp4MetaFile("film.mp4"c as int64, 0, vid);
if (ok == 0) { PrintLn("Fehler"); return 1; }
var w: int64 := peek64(vid + VID_OFF_WIDTH);
var h: int64 := peek64(vid + VID_OFF_HEIGHT);
var dur: int64 := peek64(vid + VID_OFF_DURATION_MS);
var cod: int64 := peek64(vid + VID_OFF_CODEC);
PrintLn(IntToStr(w) + "x" + IntToStr(h) + " " + IntToStr(dur / 1000) + "s");
if (cod == VID_CODEC_H264) { PrintLn("Codec: H.264"); }
if (cod == VID_CODEC_H265) { PrintLn("Codec: H.265"); }
if (cod == VID_CODEC_AV1) { PrintLn("Codec: AV1"); }
free(vid, VID_SIZE);
return 0;
}
----
===== std.video.core — Container-Erkennung =====
// Mindestens 12 Bytes erforderlich.
// Gibt VID_FMT_* zurück.
var fmt: int64 := VidDetectFormat(buf, len);
if (fmt == VID_FMT_AVI) { AviMeta(buf, len, vid); }
if (fmt == VID_FMT_MP4) { Mp4Meta(buf, len, vid); }
----
===== std.video.avi — AVI-Reader =====
==== Metadaten ====
import std.video.avi;
// Aus Speicher-Puffer
var ok: int64 := AviMeta(buf, len, vid); // 1 = Erfolg, 0 = Fehler
// Aus Datei (liest automatisch in Puffer)
// plen: Zeiger auf int64 → erhält Dateigröße; oder 0
var ok: int64 := AviMetaFile("clip.avi"c as int64, 0, vid);
AVI liefert alle Felder einschließlich FPS (aus strh.dwRate/dwScale) und Frame-Zählung (aus avih.dwTotalFrames).
==== Frame-Extraktion ====
// Anzahl '00dc'-Chunks (Video-Stream 0) in der movi-Liste
var count: int64 := AviGetFrameCount(buf, len);
// Zeiger auf Frame-Daten (innerhalb von buf), Größe in pFrameLen
// frameIdx: 0-basiert
var pFrameLen: int64 := alloc(8);
var framePtr: int64 := AviGetFrameOffset(buf, len, 0, pFrameLen);
var frameLen: int64 := peek64(pFrameLen);
==== MJPEG-Frame dekodieren ====
''AviExtractMjpegFrame'' kombiniert Frame-Suche und JPEG-Dekodierung in einem Schritt. Nur bei ''VID_CODEC_MJPEG'' sinnvoll:
import std.video.avi;
import std.image.core;
fn ExtractFrame(buf: int64, len: int64, frameIdx: int64): int64 {
var img: int64 := GrfImageAlloc(0, 0); // Größe wird vom Decoder gesetzt
var ok: int64 := AviExtractMjpegFrame(buf, len, frameIdx, img);
if (ok == 0) { GrfImageFree(img); return 0; }
return img; // GrfImage mit RGBA-Pixeln; Aufrufer muss GrfImageFree aufrufen
}
----
===== std.video.mp4 — MP4/ISOBMFF-Reader =====
import std.video.mp4;
// Aus Speicher-Puffer (erfordert 'ftyp'-Box ab Offset 4)
var ok: int64 := Mp4Meta(buf, len, vid);
// Aus Datei
var ok: int64 := Mp4MetaFile("film.mp4"c as int64, 0, vid);
Der Reader traversiert ''moov → mvhd'' (Dauer, Timescale), ''moov → trak → tkhd'' (Auflösung), ''mdia → hdlr'' ('vide'-Track), ''minf → stbl → stsd'' (Codec-Erkennung).
**Einschränkungen MP4:** FPS und Frame-Zählung sind aus dem ''moov''-Box allein nicht zuverlässig ermittelbar und werden auf ''VID_OFF_FPS_NUM=0'', ''VID_OFF_FPS_DEN=1'', ''VID_OFF_FRAME_COUNT=0'' gesetzt. Dauer und Auflösung sind immer verfügbar.
==== Codec-Erkennung (MP4) ====
Aus der ''stsd''-Box (''minf → stbl → stsd''):
^ 4CC ^ Codec ^
| ''avc1'', ''avc3'' | H.264 |
| ''hvc1'', ''hev1'' | H.265 |
| ''av01'' | AV1 |
| ''mp4v'' | MPEG-4 Part 2 |
| ''vp08'' | VP8 |
| ''vp09'' | VP9 |
==== Codec-Erkennung (AVI) ====
Aus dem ''strh.fccHandler''-Feld des Video-Streams:
^ FCC ^ Codec ^
| ''MJPG'', ''mjpg'' | MJPEG |
| ''H264'', ''avc1'', ''X264'' | H.264 |
| ''MP4V'', ''XVID'', ''DIVX'', ''DIV3'' | MPEG-4 Part 2 |
| ''hvc1'', ''HVC1'' | H.265 |
----
===== Quelldateien =====
^ Datei ^ Inhalt ^
| ''std/video/core.lyx'' | VID-00: VidMeta-Struct-Offsets, Format- und Codec-Konstanten, VidDetectFormat |
| ''std/video/avi.lyx'' | VID-01: RIFF/AVI-Parser, avih/strh-Auswertung, Frame-Extraktion, MJPEG-Dekodierung |
| ''std/video/mp4.lyx'' | VID-02: ISOBMFF-Box-Traversierung, mvhd/tkhd/hdlr/stsd-Auswertung |
Letzte Aktualisierung: 2026-06-15