shithub: rtmp

ref: 0ce01d66fb72ea51b7dd0e885a01e2bba1eda7ff
dir: /ivf.c/

View raw version
#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;
}