shithub: mcfs

Download patch

ref: 58c648070bfcaa2cfacfccdd2ffec7fe73f7af13
parent: d314994309c751e5a983797760e8386d82ae60eb
author: Sigrid Solveig Haflínudóttir <ftrvxmtrx@gmail.com>
date: Thu Apr 22 06:23:08 EDT 2021

iso: support nal lengths other than 4

--- a/iso.c
+++ b/iso.c
@@ -567,10 +567,10 @@
 dumpstc(Biobuf *f, Biobuf *out, Track *t, u8int *frame)
 {
 	SampleToChunk *stc;
-	u32int si, ch, nextch, n, len;
+	u32int si, ch, nextch, n, k, len, sz;
 	u32int samplelast, sample, rawsz, samplesz;
 	u64int ts;
-	u8int *raw;
+	u8int *raw, h[4];
 
 	raw = nil;
 	rawsz = 0;
@@ -577,6 +577,11 @@
 	sample = samplelast = 0;
 	stc = t->stc;
 	ch = 0;
+	k = t->video.avc.nallen;
+	h[0] = 0;
+	h[1] = 0;
+	h[2] = 0;
+	h[3] = 1;
 	for(si = 0; si < t->numstc; si++, stc++){
 		nextch = t->numchunks;
 		if(si+1 < t->numstc)
@@ -613,11 +618,21 @@
 						break;
 					}
 				}else if(t->video.format != 0){ /* all video goes out as IVF */
+					if(t->video.format == FmtAvc1){
+						for(sz = 0, n = 0; n < samplesz; n += k+len){
+							len = raw[n+0];
+							if(k > 1) len = len<<8 | raw[n+1];
+							if(k > 2) len = len<<8 | raw[n+2];
+							if(k > 3) len = len<<8 | raw[n+3];
+							sz += 4+len;
+						}
+					}else
+						sz = samplesz;
 					ts = tts(t, sample);
-					frame[0] = samplesz;
-					frame[1] = samplesz >> 8;
-					frame[2] = samplesz >> 16;
-					frame[3] = samplesz >> 24;
+					frame[0] = sz;
+					frame[1] = sz >> 8;
+					frame[2] = sz >> 16;
+					frame[3] = sz >> 24;
 					frame[4] = ts;
 					frame[5] = ts >> 8;
 					frame[6] = ts >> 16;
@@ -632,15 +647,15 @@
 					}
 				}
 				if(t->video.format == FmtAvc1){
-					for(n = 0; n < samplesz; n += len+4){
-						len = raw[n+0]<<24 | raw[n+1]<<16 | raw[n+2]<<8 | raw[n+3];
-						raw[n+0] = 0;
-						raw[n+1] = 0;
-						raw[n+2] = 0;
-						raw[n+3] = 1;
+					for(n = 0; n < samplesz; n += k+len){
+						len = raw[n+0];
+						if(k > 1) len = len<<8 | raw[n+1];
+						if(k > 2) len = len<<8 | raw[n+2];
+						if(k > 3) len = len<<8 | raw[n+3];
+						Bwrite(out, h, 4);
+						Bwrite(out, raw+n+k, len);
 					}
-				}
-				if(Bwrite(out, raw, samplesz) != samplesz){ /* EOF? */
+				}else if(Bwrite(out, raw, samplesz) != samplesz){ /* EOF? */
 					werrstr("eof");
 					break;
 				}
@@ -656,9 +671,9 @@
 static int
 dumptrun(Biobuf *f, Biobuf *out, Track *t, u8int *frame)
 {
-	int i, j, len, n;
+	int i, j, len, n, k;
 	u64int ts;
-	u8int *raw;
+	u8int *raw, h[4];
 	int maxsz, sz;
 	RunSample *s;
 	Moof *m;
@@ -668,6 +683,11 @@
 	ts = 0;
 	maxsz = 0;
 	raw = nil;
+	k = t->video.avc.nallen;
+	h[0] = 0;
+	h[1] = 0;
+	h[2] = 0;
+	h[3] = 1;
 	for(i = 0, m = t->moof; i < t->nmoof; i++, m++){
 		for(j = 0; j < m->trun.trun.samplecount; j++){
 			s = &m->trun.trun.samples[j];
@@ -717,15 +737,27 @@
 					return -1;
 				}
 				if(t->video.format == FmtAvc1){
-					for(n = 12; n < 12+s->size; n += len+4){
-						len = raw[n+0]<<24 | raw[n+1]<<16 | raw[n+2]<<8 | raw[n+3];
-						raw[n+0] = 0;
-						raw[n+1] = 0;
-						raw[n+2] = 0;
-						raw[n+3] = 1;
+					for(sz = 0, n = 12; n < 12+s->size; n += len+k){
+						len = raw[n+0];
+						if(k > 1) len = len<<8 | raw[n+1];
+						if(k > 2) len = len<<8 | raw[n+2];
+						if(k > 3) len = len<<8 | raw[n+3];
+						sz += 4+len;
 					}
-				}
-				if(Bwrite(out, raw, 12 + s->size) != 12 + s->size) /* eof? */
+					raw[0] = sz;
+					raw[1] = sz >> 8;
+					raw[2] = sz >> 16;
+					raw[3] = sz >> 24;
+					Bwrite(out, raw, 12);
+					for(n = 12; n < 12+s->size; n += len+k){
+						len = raw[n+0];
+						if(k > 1) len = len<<8 | raw[n+1];
+						if(k > 2) len = len<<8 | raw[n+2];
+						if(k > 3) len = len<<8 | raw[n+3];
+						Bwrite(out, h, 4);
+						Bwrite(out, raw+n+k, len);
+					}
+				}else if(Bwrite(out, raw, 12 + s->size) != 12 + s->size) /* eof? */
 					break;
 				ts += s->duration; /* sample's "time offset" is ignored here */
 			}else{
@@ -740,7 +772,7 @@
 static int
 dumptrack(Biobuf *f, int id)
 {
-	int i, j, x, res;
+	int i, j, x, k, res;
 	Biobuf out;
 	u64int dur;
 	Track *t;
@@ -832,8 +864,8 @@
 		Bwrite(&out, frame, 0x20);
 
 		if(t->video.format == FmtAvc1){
-			if(t->video.avc.nallen != 4){
-				werrstr("avc1 nallen != 4 isn't supported yet");
+			if(t->video.avc.nallen < 1 || t->video.avc.nallen > 4){
+				werrstr("avc1: invalid nallen %d", t->video.avc.nallen);
 				return -1;
 			}
 			memset(frame, 0, 4+8+4);