====== 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