ref: c9a45262d2655e843fcc0ad7382f08efcc523926
dir: /ivf.c/
#include <u.h> #include <libc.h> #include <bio.h> #include "ivf.h" #include "util.h" static int Bu16le(Biobuf *b, u16int *o) { int x; x = Bgetc(b); x |= Bgetc(b)<<8; *o = x; if(x < 0) werrstr("failed to read 2 bytes"); return x < 0 ? -1 : 0; } static int Bu32le(Biobuf *b, u32int *o) { int x, i; *o = 0; for(i = 0; i < 4; *o |= x<<(i*8), i++){ if((x = Bgetc(b)) < 0){ werrstr("failed to read 4 bytes"); return -1; } } return 0; } static int Bu64le(Biobuf *b, u64int *o) { int x, i; *o = 0; for(i = 0; i < 8; *o |= (uvlong)x<<(i*8), i++){ if((x = Bgetc(b)) < 0){ werrstr("failed to read 8 bytes"); return -1; } } return 0; } int ivfopen(Biobuf *v, IVF *ivf) { u16int hlen; u8int b[6]; if(Bread(v, b, 6) != 6 || Bu16le(v, &hlen) < 0 || hlen < 0x20 || memcmp(b, "DKIF", 4) != 0 || Bread(v, b, 4) != 4){ werrstr("invalid header"); goto err; } memmove(ivf->type, b, 4); ivf->v = v; ivf->type[4] = 0; ivf->ns₀ = Zns₀; if(Bu16le(v, &ivf->w) < 0 || Bu16le(v, &ivf->h) < 0 || Bu32le(v, &ivf->tbdenum) < 0 || Bu32le(v, &ivf->tbnum) < 0){ werrstr("invalid data"); goto err; } if(Bseek(v, hlen, 0) != hlen){ werrstr("broken stream"); goto err; } return 0; err: werrstr("ivfopen: %r"); return -1; } static u64int ivfns(IVF *ivf, u64int ts) { return ts * (ivf->tbnum * 1000000000ULL / ivf->tbdenum); } int ivfread(IVF *ivf, IVFrame *f) { u64int ts; u32int sz; int n; if(Bu32le(ivf->v, &sz) < 0 || Bu64le(ivf->v, &ts) < 0 || (int)sz < 0){ /* eof */ f->sz = 0; return 0; } if(sz > f->bufsz){ f->bufsz = sz*2; f->buf = erealloc(f->buf, sz*2); } if((n = Bread(ivf->v, f->buf, sz)) != sz){ werrstr("short read (%d < %d)", n, sz); goto err; } if(ivf->ns₀ == Zns₀) ivf->ns₀ = ivfns(ivf, ts); f->sz = sz; f->ns = ivfns(ivf, ts) - ivf->ns₀; return 0; err: werrstr("ivfread: %r"); return -1; }