shithub: mcfs

ref: 24a65311b538504923aaee04393fd363c2a63356
dir: /ivf.c/

View raw version
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "common.h"

enum {
	Timedenum = 1000ULL,
};

int
ivfpacket(Biobuf *out, Framectx *ctx, u8int *buf, int sz, uvlong ts)
{
	u8int d[0x20];
	uvlong dur;
	int n, len;

	dur = ctx->duration / 1000000ULL;
	ts = ts / 1000000ULL;

	if(ctx->frid == 0){
		memmove(d, "DKIF", 4);
		d[4] = 0;
		d[5] = 0;
		d[6] = 0x20;
		d[7] = 0;
		if(ctx->fmt == FmtAv01)
			memmove(d+8, "AV01", 4);
		else if(ctx->fmt == FmtAvc1)
			memmove(d+8, "AVC1", 4);
		else if(ctx->fmt == FmtVp08)
			memmove(d+8, "VP80", 4);
		else if(ctx->fmt == FmtVp09)
			memmove(d+8, "VP90", 4);
		else{
			werrstr("unsupported video format %T", ctx->fmt);
			goto err;
		}
		d[12] = ctx->video.width;
		d[13] = ctx->video.width >> 8;
		d[14] = ctx->video.height;
		d[15] = ctx->video.height >> 8;
		/* timebase denum */
		d[16] = Timedenum;
		d[17] = Timedenum >> 8;
		d[18] = Timedenum >> 16;
		d[19] = Timedenum >> 24;
		/* timebase num */
		d[20] = 1;
		d[21] = 0;
		d[22] = 0;
		d[23] = 0;
		/* FIXME is it a "number of frames" or "total duration?" */
		d[24] = dur;
		d[25] = dur >> 8;
		d[26] = dur >> 16;
		d[27] = dur >> 24;
		d[28] = dur >> 32; /* FIXME is it 64 bits? */
		d[29] = dur >> 40;
		d[30] = dur >> 48;
		d[31] = dur >> 56;

		if(Bwrite(out, d, 0x20) != 0x20)
			goto err;
	}

	d[0] = sz;
	d[1] = sz >> 8;
	d[2] = sz >> 16;
	d[3] = sz >> 24;
	d[4] = ts;
	d[5] = ts >> 8;
	d[6] = ts >> 16;
	d[7] = ts >> 24;
	d[8] = ts >> 32;
	d[9] = ts >> 40;
	d[10] = ts >> 48;
	d[11] = ts >> 56;
	if(Bwrite(out, d, 12) != 12)
		goto err;
	if(ctx->fmt == FmtAvc1){
		for(n = 0; n < sz; n += len+4){
			len = buf[n+0]<<24 | buf[n+1]<<16 | buf[n+2]<<8 | buf[n+3];
			buf[n+0] = 0;
			buf[n+1] = 0;
			buf[n+2] = 0;
			buf[n+3] = 1;
		}
	}
	if(Bwrite(out, buf, sz) != sz)
		goto err;
	ctx->frid++;

	return 0;
err:
	werrstr("ivfpacket: %r");
	return -1;
}