shithub: mcfs

ref: 041e2ada566d991e41dc0f626d1d20582276a6c0
dir: /common.h/

View raw version
enum {
	Nodump = -1,
	Dumpaudio = -2,
	Dumpvideo = -3,

	FmtAv01 = 0x61763031u,
	FmtAvc1 = 0x61766331u,
	FmtMp4a = 0x6d703461u,
	FmtOpus = 0x6f707573u,
	FmtVp08 = 0x76703038u,
	FmtVp09 = 0x76703039u,

	/* fake ones, not supposed to show up in a mp4 */
	FmtVorbis = 0x766f7262u,
	FmtSrt = 0x00737274u, /* srt subtitles */
	FmtMp3 = 0x006d7033u,
};

typedef struct Ebml Ebml;
typedef struct Packet Packet;
typedef struct Packetctx Packetctx;
typedef int (*packet_f)(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);

struct Packet {
	uchar *data;
	int sz;
};

struct Packetctx {
	uvlong frid;
	uvlong duration;
	uvlong seekpreroll;
	vlong discardpad;
	vlong blockdur;
	struct {
		char name[16];
		vlong delay;
		struct {
			uchar *data;
			int sz;
		}priv;
	}codec;
	u32int trackuid;
	u32int fmt;

	struct {
		int width, height;
		struct {
			int left, right, top, bottom;
		}crop;
		struct {
			int width, height;
			int unit;
			int aspectmode;
		}display;
	}video;
	struct {
		float samplerate;
		int channels;
		int bps;
	}audio;
};

struct Ebml {
	Packetctx;

	packet_f fpacket;

	vlong timestampscale;
	vlong perframe;
	int tracknum;
	int tracktype;
	vlong codecdelay;
	char lang[8];
};

extern Biobuf stderr, out;
extern int dflag, trackdump;

#pragma varargck type "T" u32int
int isotypefmt(Fmt *f);

#pragma varargck type "P" uvlong
int srttsfmt(Fmt *f);

int isorun(Biobuf *f);
int ebmlrun(Biobuf *f);

u32int crc32(u32int init, u8int *d, ulong len);

int ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
int oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
int srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);

int ebmlint(Biobuf *f, vlong *out, int isid);
vlong ebmlel(Biobuf *f, vlong sz, vlong *id, vlong *esz);
vlong ebmlrawint(Biobuf *f, vlong sz, vlong *dst);

#define ebmlgetnumber(expid, dest) \
	if(id == expid){ \
		vlong x; \
		if(ebmlrawint(f, sz, &x) < 0) \
			return -1; \
		dest = x; \
		left -= sz; \
		continue; \
	}

#define ebmlgetstring(expid, dest) \
	if(id == expid){ \
		n = min(sizeof(dest)-1, sz); \
		if(Bread(f, dest, n) != n) \
			return -1; \
		dest[n] = 0; \
		if(n != sz) \
			Bseek(f, sz-n, 1); \
		left -= sz; \
		continue; \
	}

#define ebmlgetbytes(expid, dest) \
	if(id == expid){ \
		dest.data = malloc(sz); \
		if(Bread(f, dest.data, sz) != sz) \
			return -1; \
		dest.sz = sz; \
		left -= sz; \
		continue; \
	}

#define ebmlgetfloat(expid, dest) \
	if(id == expid){ \
		u32int u; \
		union { \
			uchar b[8]; \
			u32int u[2]; \
			float f; \
			double d; \
		}x; \
		if(sz == 4){ \
			if(Bread(f, x.b, 4) != 4) \
				return -1; \
			x.u[0] = (x.u[0]&0xff000000)>>24 | (x.u[0]&0x00ff0000)>>8 | (x.u[0]&0x0000ff00)<<8 | (x.u[0]&0x000000ff)<<24; \
			dest = x.f; \
		}else if(sz == 8){ \
			if(Bread(f, x.b, 8) != 8) \
				return -1; \
			u = (x.u[0]&0xff000000)>>24 | (x.u[0]&0x00ff0000)>>8 | (x.u[0]&0x0000ff00)<<8 | (x.u[0]&0x000000ff)<<24; \
			x.u[0] = (x.u[1]&0xff000000)>>24 | (x.u[1]&0x00ff0000)>>8 | (x.u[1]&0x0000ff00)<<8 | (x.u[1]&0x000000ff)<<24; \
			x.u[1] = u; \
			dest = x.d; \
		}else{ \
			werrstr("invalid float size"); \
			break; \
		} \
		left -= sz; \
		continue; \
	}

#define min(a,b) ((a)<=(b)?(a):(b))