shithub: mcfs

Download patch

ref: 1cd6fa1aa2cd7eb7fc2beebec6ae51eb25450971
parent: cb8864eb448c73bf5ade441f12b00ead0d0a86a1
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon Mar 16 23:54:47 EDT 2020

extract raw streams

--- a/iso.c
+++ b/iso.c
@@ -4,6 +4,8 @@
 
 typedef struct Box Box;
 typedef struct RunSample RunSample;
+typedef struct Track Track;
+typedef struct SampleToChunk SampleToChunk;
 
 struct Box {
 	vlong dsz;
@@ -88,11 +90,7 @@
 
 		struct {
 			u32int entrycount;
-			struct {
-				u32int firstchunk;
-				u32int samplesperchunk;
-				u32int sdt;
-			}*entry;
+			SampleToChunk *entry;
 		}stsc;
 
 		struct {
@@ -129,6 +127,25 @@
 	vlong timeoffset;
 };
 
+struct Track {
+	u64int *chunkoffset;
+	u32int numchunks;
+
+	u32int *samplesize;
+	u32int numsamples;
+
+	SampleToChunk *stc;
+	u32int numstc;
+
+	int id;
+};
+
+struct SampleToChunk {
+	u32int firstchunk;
+	u32int samplesperchunk;
+	u32int sdt;
+};
+
 enum {
 	BoxUuid = 0x75756964u,
 	BoxFtyp = 0x66747970u,
@@ -146,6 +163,7 @@
 				BoxMinf = 0x6d696e66u,
 					BoxDinf = 0x64696e66u,
 					BoxStbl = 0x7374626cu,
+						BoxCtts = 0x63747473u,
 					BoxStsd = 0x73747364u,
 					BoxStts = 0x73747473u,
 					BoxStsc = 0x73747363u,
@@ -173,7 +191,7 @@
 	b->type == BoxMfhd || b->type == BoxTfhd || b->type == BoxTfdt || b->type == BoxTrun || \
 	b->type == BoxStsd || b->type == BoxStts || b->type == BoxStss || b->type == BoxTkhd || \
 	b->type == BoxElst || b->type == BoxStsc || b->type == BoxStco || b->type == BoxCo64 || \
-	b->type == BoxStsz \
+	b->type == BoxStsz || b->type == BoxCtts \
 )
 
 #define eBread(sz, e) if(Bread(f, d, (sz)) != (sz)){ werrstr(e); goto err; }
@@ -180,8 +198,11 @@
 
 static int dflag;
 static int dind;
+static int trackdump = -1;
 static u32int defsamplesize;
 
+static Track track;
+
 static int parsebox(Biobuf *f, Box *b, int *eof);
 
 #pragma varargck type "T" u32int
@@ -332,6 +353,47 @@
 	}
 }
 
+static void
+dumptrack(Biobuf *f)
+{
+	SampleToChunk *stc;
+	u32int si, ch, lastch;
+	u32int samplelast, sample, rawsz;
+	vlong o;
+	u8int *raw;
+	Biobuf out;
+
+	Binit(&out, 1, OWRITE);
+	raw = nil;
+	rawsz = 0;
+	sample = samplelast = 0;
+	stc = track.stc;
+	for(si = 0; si < track.numstc; si++, stc++){
+		lastch = si+1 < track.numstc ? stc[1].firstchunk : track.numchunks;
+		for(ch = stc->firstchunk-1; ch < lastch && ch < track.numchunks; ch++){
+			o = track.chunkoffset[ch];
+			if(Bseek(f, o, 0) != o)
+				sysfatal("chunk %ud: %r", ch);
+			for(; sample < samplelast+stc->samplesperchunk && sample < track.numsamples; sample++){
+				if(track.samplesize[sample] == 0)
+					break;
+				if(rawsz < track.samplesize[sample]){
+					rawsz = track.samplesize[sample] * 2;
+					raw = realloc(raw, rawsz);
+				}
+				if(Bread(f, raw, track.samplesize[sample]) != track.samplesize[sample])
+					sysfatal("chunk %ud sample %ud size %ud: %r", ch, sample, track.samplesize[sample]);
+				if(Bwrite(&out, raw, track.samplesize[sample]) != track.samplesize[sample])
+					exits(nil);
+			}
+			samplelast = sample;
+		}
+	}
+	fprint(2, "%ud samples\n", sample);
+	Bterm(&out);
+	free(raw);
+};
+
 static int
 parseboxdata(Biobuf *f, Box *b)
 {
@@ -369,6 +431,17 @@
 			if(inner.dstart+inner.dsz >= b->dstart+b->dsz)
 				break;
 		}
+		if(b->type == BoxTrak){
+			if(track.id == trackdump){
+				u = Boffset(f);
+				dumptrack(f);
+				Bseek(f, u, 0);
+			}
+			free(track.chunkoffset);
+			free(track.samplesize);
+			free(track.stc);
+			memset(&track, 0, sizeof(track));
+		}
 		dind--;
 	}else if(b->type == BoxMvhd){
 		n = b->version == 0 ? 96 : 108;
@@ -506,7 +579,7 @@
 	}else if(b->type == BoxStsc){
 		eBread(4, "entry_count");
 		b->stsc.entrycount = bu32(d);
-		b->stsc.entry = calloc(b->stsc.entrycount, sizeof(*b->stsc.entry));
+		b->stsc.entry = calloc(b->stsc.entrycount, sizeof(SampleToChunk));
 		for(u = 0; u < b->stsc.entrycount; u++){
 			eBread(4, "first_chunk");
 			b->stsc.entry[u].firstchunk = bu32(d);
@@ -515,6 +588,8 @@
 			eBread(4, "sample_description_table");
 			b->stsc.entry[u].sdt = bu32(d);
 		}
+		track.numstc = b->stsc.entrycount;
+		track.stc = b->stsc.entry;
 		printbox(b);
 	}else if(b->type == BoxStco || b->type == BoxCo64){
 		eBread(4, "entry_count");
@@ -524,6 +599,8 @@
 			eBread(b->type == BoxStco ? 4 : 8, "chunk_offset");
 			b->stco_co64.chunkoffset[u] = b->type == BoxStco ? bu32(d) : bu64(d);
 		}
+		track.numchunks = b->stco_co64.entrycount;
+		track.chunkoffset = b->stco_co64.chunkoffset;
 		printbox(b);
 	}else if(b->type == BoxStsz){
 		eBread(4, "sample_size");
@@ -536,6 +613,8 @@
 				eBread(4, "chunk_offset");
 				b->stsz.entrysize[u] = bu32(d);
 			}
+			track.numsamples = b->stsz.samplecount;
+			track.samplesize = b->stsz.entrysize;
 		}
 		printbox(b);
 	}else if(b->type == BoxTkhd){
@@ -546,6 +625,7 @@
 			b->tkhd.modtime = bu64(d);
 			eBread(8, "track_id"); /* skipping 4 reserved as well */
 			b->tkhd.trackid = bu32(d);
+			track.id = b->tkhd.trackid;
 			eBread(8, "duration");
 			b->tkhd.duration = bu64(d);
 		}else if(b->version == 0){
@@ -555,6 +635,7 @@
 			b->tkhd.modtime = bu32(d);
 			eBread(8, "track_id"); /* skipping 4 reserved as well */
 			b->tkhd.trackid = bu32(d);
+			track.id = b->tkhd.trackid;
 			eBread(4, "duration");
 			b->tkhd.duration = bu32(d);
 		}else{
@@ -651,6 +732,13 @@
 	return -1;
 }
 
+static void
+usage(void)
+{
+	fprint(2, "usage: iso [-d] [-t TRACK] FILE\n");
+	exits("usage");
+}
+
 int
 main(int argc, char **argv)
 {
@@ -662,6 +750,9 @@
 	ARGBEGIN{
 	case 'd':
 		dflag = 1;
+		break;
+	case 't':
+		trackdump = atoi(EARGF(usage()));
 		break;
 	}ARGEND