shithub: mcfs

Download patch

ref: 9b440b0772b355b601858ad2c3a8f8432f17fde9
parent: 383cac91b7b55a33dd04896cfab5b030e8877412
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Sat Dec 12 20:20:25 EST 2020

ebml: support h.264

--- a/ebml.c
+++ b/ebml.c
@@ -166,6 +166,8 @@
 			e->fmt = FmtVp09;
 		else if(strcmp(c, "vp8") == 0)
 			e->fmt = FmtVp08;
+		else if(strcmp(e->codec.name, "V_MPEG4/ISO/AVC") == 0)
+			e->fmt = FmtAvc1;
 		else
 			goto err;
 		e->fpacket = ivfpacket;
@@ -195,7 +197,7 @@
 	}
 
 err:
-	werrstr("don't know how to remux %s", c);
+	werrstr("don't know how to remux %s (track type %d)", e->codec.name, e->tracktype);
 
 	return -1;
 }
--- a/ivf.c
+++ b/ivf.c
@@ -7,12 +7,45 @@
 	Timedenum = 1000ULL,
 };
 
+static int
+ivfframe(Biobuf *out, u8int *p, int sz, uvlong ts, int avcsplit)
+{
+	u8int d[12];
+	int n, len;
+
+	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)
+		return -1;
+	if(avcsplit){
+		for(n = 0; n < sz; n += len+4){
+			len = p[n+0]<<24 | p[n+1]<<16 | p[n+2]<<8 | p[n+3];
+			p[n+0] = 0;
+			p[n+1] = 0;
+			p[n+2] = 0;
+			p[n+3] = 1;
+		}
+	}
+
+	return Bwrite(out, p, sz) != sz ? -1 : 0;
+}
+
 int
 ivfpacket(Biobuf *out, Packetctx *ctx, Packet *p, int np, uvlong ts)
 {
-	u8int d[0x20];
+	u8int d[0x20], *x, *y;
+	int i, n, len;
 	uvlong dur;
-	int n, len;
 
 	dur = ctx->duration / 1000000ULL;
 	ts = ts / 1000000ULL;
@@ -62,32 +95,47 @@
 
 			if(Bwrite(out, d, 0x20) != 0x20)
 				goto err;
-		}
 
-		d[0] = p[0].sz;
-		d[1] = p[0].sz >> 8;
-		d[2] = p[0].sz >> 16;
-		d[3] = p[0].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 < p[0].sz; n += len+4){
-				len = p[0].data[n+0]<<24 | p[0].data[n+1]<<16 | p[0].data[n+2]<<8 | p[0].data[n+3];
-				p[0].data[n+0] = 0;
-				p[0].data[n+1] = 0;
-				p[0].data[n+2] = 0;
-				p[0].data[n+3] = 1;
+			if(ctx->codec.priv.sz > 0){
+				if(ctx->fmt != FmtAvc1){
+					werrstr("no idea what to do with codec private data");
+					goto err;
+				}
+
+				x = ctx->codec.priv.data;
+				/* FIXME make sure it's actually a proper AVC decoder configuration record */
+				/* FIXME nal unit length: might not be 4 at all times */
+				/* sps */
+				x[0] = 0;
+				x[1] = 0;
+				x[2] = 0;
+				x[3] = 1;
+				n = x[5] & 0x1f;
+				y = x+6;
+				for(i = 0; i < n; i++){
+					len = y[0] << 8 | y[1];
+					y += 2;
+					memmove(x+4, y, len);
+					if(ivfframe(out, x, 4+len, 0, 0) != 0)
+						goto err;
+					ctx->frid++;
+					y += len;
+				}
+				/* pps */
+				n = *y++;
+				for(i = 0; i < n; i++){
+					len = y[0] << 8 | y[1];
+					y += 2;
+					memmove(x+4, y, len);
+					if(ivfframe(out, x, 4+len, 0, 0) != 0)
+						goto err;
+					ctx->frid++;
+					y += len;
+				}
 			}
 		}
-		if(Bwrite(out, p[0].data, p[0].sz) != p[0].sz)
+
+		if(ivfframe(out, p[0].data, p[0].sz, ts, ctx->fmt == FmtAvc1) != 0)
 			goto err;
 		ctx->frid++;
 	}