shithub: mcfs

ref: bbba27dbb73cf46b659a707a425be7d8fd8097fe
dir: /extra/ivf2raw.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.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;
}

static void
usage(void)
{
	fprint(2, "usage: %s <file.ivf >file.raw\n", argv0);
	exits("usage");
}

void
main(int argc, char **argv)
{
	int n, bufsz, framenum;
	u32int tbnum, tbdenum;
	u16int w, h, hlen;
	u64int timestamp;
	Biobuf in, out;
	char tmp[6];
	u8int *buf;
	u32int sz;

	ARGBEGIN{
	}ARGEND

	if(argc != 0)
		usage();

	Binit(&in, 0, OREAD);
	Binit(&out, 1, OWRITE);

	if(Bread(&in, tmp, 6) != 6 || Bu16le(&in, &hlen) < 0)
		sysfatal("header read failed");
	if(memcmp(tmp, "DKIF", 4) != 0)
		sysfatal("expected DKIF, got %02x%02x%02x%02x", tmp[0], tmp[1], tmp[2], tmp[3]);
	if(hlen < 0x20 || Bread(&in, tmp, 4) != 4)
		sysfatal("invalid header: hlen=%d", hlen);
	if(Bu16le(&in, &w) < 0 || Bu16le(&in, &h) < 0 || Bu32le(&in, &tbdenum) < 0 || Bu32le(&in, &tbnum) < 0)
		sysfatal("invalid header: %r");
	if(Bseek(&in, hlen, 0) != hlen)
		sysfatal("invalid IVF stream");

	bufsz = 0;
	buf = nil;
	for(framenum = 0;; framenum++){
		if(Bu32le(&in, &sz) < 0 || Bu64le(&in, &timestamp) || (int)sz < 0)
			break;
		if(bufsz < sz){
			bufsz = sz;
			if((buf = realloc(buf, bufsz)) == nil)
				sysfatal("frame %d is too big: %d bytes", framenum, bufsz);
		}
		if((n = Bread(&in, buf, sz)) != sz)
			sysfatal("short read (%d < %d)", n, sz);
		Bwrite(&out, buf, sz);
	}

	Bterm(&in);
	Bterm(&out);

	exits(nil);
}