~ft/mcfs

c5d4cd0d1a217b849ecbe219d11145c872941d2b — Sigrid Solveig Haflínudóttir 2 years ago 7996b42
prepare matroska remuxer to handle key frames in special ways
5 files changed, 91 insertions(+), 59 deletions(-)

M aac.c
M matroska.c
M ogg.c
M packet.h
M srt.c
M aac.c => aac.c +2 -2
@@ 24,13 24,13 @@ static int ratecfg[] = {
};

int
aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key)
{
	int i, chanc, ratei, objt, sz;
	u16int x;
	char *c;

	USED(ts);
	USED(ts, key);
	if(ctx->frid == 0){ /* set up ADTS */
		ctx->adts[0] = 0xff; /* syncword */
		ctx->adts[1] = 0xf1; /* syncword, mpeg4, no crc */

M matroska.c => matroska.c +65 -49
@@ 102,7 102,7 @@ format(Ebml *e)
}

static int
asispacket(Biobuf *out, Packetctx *, Packet *p, int np, uvlong)
asispacket(Biobuf *out, Packetctx *, Packet *p, int np, uvlong, int)
{
	int i;



@@ 187,11 187,17 @@ trackinfo(Biobuf *o, Ebml *e)
	Bprint(o, "\n");
}

static void
flush(Ebml *e, int refblock)
{
	USED(e); USED(refblock);
}

int
matroskarun(Biobuf *f)
{
	vlong left, n, sz, nsz, bufsz, track, off, packetsz, x, endtracks;
	int isebml, npackets, i, skipdata, lacing;
	vlong left, n, sz, nsz, bufsz, track, off, packetsz, x, endtracks, bgend;
	int isebml, npackets, i, skipdata, lacing, refblock, key;
	uvlong ts, timestamp, timestampscale;
	double duration;
	s16int timecode;


@@ 212,6 218,8 @@ matroskarun(Biobuf *f)
	duration = 0;
	skipdata = trackdump == Nodump;
	el.id = 0;
	refblock = 0;
	bgend = 0;
	for(isebml = 0; left != 0;){
		if(el.id == EBlockDuration)
			te.blockdur *= timestampscale;


@@ 234,6 242,10 @@ matroskarun(Biobuf *f)
			break;
		}
		left -= n;
		if(off >= bgend && !skipdata){
			flush(&te, refblock);
			refblock = 0;
		}

		if(el.id == EEBML){ /* EBML comes first */
			if(isebml != 0){


@@ 282,6 294,8 @@ matroskarun(Biobuf *f)
		}else if(el.id == EContentEncodings || el.id == EContentEncoding || el.id == EContentCompression){
			continue;
		}else if(el.id == EBlockGroup && !skipdata){
			refblock = 0;
			bgend = off+sz;
			continue;
		}else if((el.id == ESimpleBlock || el.id == EBlock) && !skipdata){
			if(te.tracknum == -1)


@@ 315,6 329,7 @@ matroskarun(Biobuf *f)
				sz -= 3;
				timecode = buf[0]<<8 | buf[1];
				lacing = (buf[2] >> 1) & 3;
				key = buf[2] & 0x80;
				npackets = buf[3]+1;

				if(te.comp.algo == 3){ /* header stripping, need to put bytes back */


@@ 415,55 430,56 @@ matroskarun(Biobuf *f)

				/* ns timestamp */
				ts = (timestamp + timecode) * timestampscale - te.codec.delay;
				if(te.fpacket(&out, &te, packets, npackets, ts) != 0)
				if(te.fpacket(&out, &te, packets, npackets, ts, key) != 0)
					goto err;
				continue;
			}
		}else{
				getnumber(ETimestampScale, timestampscale)
			else
				getfloat(ESamplingFrequency, e.audio.samplerate)
			else
				getfloat(EOutputSamplingFrequency, e.audio.outsamplerate)
			else
				getnumber(EChannels, e.audio.channels)
			else
				getnumber(EBitDepth, e.audio.bps)
			else
				getnumber(ETrackNumber, e.tracknum)
			else
				getnumber(ETrackType, e.tracktype)
			else
				getstring(ECodecID, e.codec.name)
			else
				getbytes(ECodecPrivate, e.codec.priv)
			else
				getnumber(ECodecDelay, e.codec.delay)
			else
				getnumber(EContentCompAlgo, e.comp.algo)
			else
				getbytes(EContentCompSettings, e.comp)
			else
				getnumber(EPixelWidth, e.video.width)
			else
				getnumber(EPixelHeight, e.video.height)
			else
				getnumber(ETimestamp, timestamp)
			else
				getnumber(EDefaultDuration, e.perframe)
			else
				getnumber(ESeekPreRoll, e.seekpreroll)
			else
				getfloat(EDuration, duration)
			else
				getnumber(ETrackUID, e.trackuid)
			else
				getsigned(EDiscardPadding, te.discardpad)
			else
				getnumber(EBlockDuration, te.blockdur)
			else
				getstring(ELanguage, e.lang)
		}
		}else
			getnumber(EReferenceBlock, refblock)
		else
			getnumber(ETimestampScale, timestampscale)
		else
			getfloat(ESamplingFrequency, e.audio.samplerate)
		else
			getfloat(EOutputSamplingFrequency, e.audio.outsamplerate)
		else
			getnumber(EChannels, e.audio.channels)
		else
			getnumber(EBitDepth, e.audio.bps)
		else
			getnumber(ETrackNumber, e.tracknum)
		else
			getnumber(ETrackType, e.tracktype)
		else
			getstring(ECodecID, e.codec.name)
		else
			getbytes(ECodecPrivate, e.codec.priv)
		else
			getnumber(ECodecDelay, e.codec.delay)
		else
			getnumber(EContentCompAlgo, e.comp.algo)
		else
			getbytes(EContentCompSettings, e.comp)
		else
			getnumber(EPixelWidth, e.video.width)
		else
			getnumber(EPixelHeight, e.video.height)
		else
			getnumber(ETimestamp, timestamp)
		else
			getnumber(EDefaultDuration, e.perframe)
		else
			getnumber(ESeekPreRoll, e.seekpreroll)
		else
			getfloat(EDuration, duration)
		else
			getnumber(ETrackUID, e.trackuid)
		else
			getsigned(EDiscardPadding, te.discardpad)
		else
			getnumber(EBlockDuration, te.blockdur)
		else
			getstring(ELanguage, e.lang)

		if(sz > 0){
			if(Bseek(f, sz, 1) < 0)

M ogg.c => ogg.c +8 -2
@@ 71,7 71,7 @@ packet(Biobuf *out, Packetctx *ctx, int htype, Packet *p, int np, uvlong granule
}

int
oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key)
{
	/*                     magic                            vendor len   list len */
	u8int opuscomment[] = {'O','p','u','s','T','a','g','s', 0,0,0,0,     0,0,0,0};


@@ 81,8 81,8 @@ oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
	int sgszs[4];
	Packet onep;

	USED(key);
	ts += ctx->seekpreroll - ctx->discardpad;
	gr = (ts * 48) / 1000000;

	if(ctx->frid == 0){ /* first packet? */
		d = ctx->codec.priv.data;


@@ 130,6 130,12 @@ oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
		}
	}

	if(ctx->fmt == FmtTheora){
		gr = 0;
	}else{
		gr = (ts * 48) / 1000000;
	}

	if(np > 0 && packet(out, ctx, ctx->discardpad ? 4 : 0, p, np, gr) != 0)
		goto err;


M packet.h => packet.h +14 -5
@@ 1,7 1,7 @@
typedef struct Packet Packet;
typedef struct Packetctx Packetctx;

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

struct Packet {
	uchar *data;


@@ 30,6 30,8 @@ struct Packetctx {
	u32int trackuid;
	u32int fmt;

	int key;

	struct {
		int width;
		int height;


@@ 40,10 42,17 @@ struct Packetctx {
		int channels;
		int bps;
	}audio;

	/* private stuff for packet_f functions */
	uchar adts[7];
	struct {
		uchar *p;
		int n;
	}ps[16];
	int nps;
};

int aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts);
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 aacpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
int ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
int oggpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);
int srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key);

M srt.c => srt.c +2 -1
@@ 31,11 31,12 @@ srttsfmt(Fmt *f)
}

int
srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
srtpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts, int key)
{
	int i, n;
	uchar *s, *o;

	USED(key);
	for(i = 0; i < np; i++, p++){
		for(s = o = p->data, n = 0; n < p->sz;){
			if(*s == '\r'){