ref: 36986cc948a8f422bed5631bf3582ce5657bcde3
dir: /ivf.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "ivf.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 |= 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->type[4] = 0;
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;
}
int
ivfread(Biobuf *v, IVFrame *f)
{
u8int *buf;
u64int ts;
u32int sz;
int n;
if(Bu32le(v, &sz) < 0 || Bu64le(v, &ts) < 0 || (int)sz < 0){
/* eof */
f->sz = 0;
return 0;
}
buf = f->buf;
if(sz > f->bufsz){
if((buf = realloc(f->buf, sz)) == nil){
werrstr("frame is too big: %d bytes", sz);
goto err;
}
f->buf = buf;
}
if((n = Bread(v, buf, sz)) != sz){
werrstr("short read (%d < %d)", n, sz);
goto err;
}
f->buf = buf;
f->sz = sz;
f->ts = ts;
return 0;
err:
werrstr("ivfread: %r");
return -1;
}
u64int
ivfns(IVF *ivf, u64int ts)
{
return ts * ivf->tbnum * 1000000000ULL / ivf->tbdenum;
}