~ft/mcfs

1cd6fa1aa2cd7eb7fc2beebec6ae51eb25450971 — Sigrid Haflínudóttir 7 months ago cb8864e
extract raw streams
1 files changed, 98 insertions(+), 7 deletions(-)

M iso.c
M iso.c => iso.c +98 -7
@@ 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 Box {

		struct {
			u32int entrycount;
			struct {
				u32int firstchunk;
				u32int samplesperchunk;
				u32int sdt;
			}*entry;
			SampleToChunk *entry;
		}stsc;

		struct {


@@ 129,6 127,25 @@ struct RunSample {
	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 @@ enum {
				BoxMinf = 0x6d696e66u,
					BoxDinf = 0x64696e66u,
					BoxStbl = 0x7374626cu,
						BoxCtts = 0x63747473u,
					BoxStsd = 0x73747364u,
					BoxStts = 0x73747473u,
					BoxStsc = 0x73747363u,


@@ 173,15 191,18 @@ enum {
	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; }

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 @@ printbox(Box *b)
	}
}

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 @@ parseboxdata(Biobuf *f, Box *b)
			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 @@ parseboxdata(Biobuf *f, Box *b)
	}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 @@ parseboxdata(Biobuf *f, Box *b)
			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 @@ parseboxdata(Biobuf *f, Box *b)
			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 @@ parseboxdata(Biobuf *f, Box *b)
				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 @@ parseboxdata(Biobuf *f, Box *b)
			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 @@ parseboxdata(Biobuf *f, Box *b)
			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 @@ err:
	return -1;
}

static void
usage(void)
{
	fprint(2, "usage: iso [-d] [-t TRACK] FILE\n");
	exits("usage");
}

int
main(int argc, char **argv)
{


@@ 663,6 751,9 @@ main(int argc, char **argv)
	case 'd':
		dflag = 1;
		break;
	case 't':
		trackdump = atoi(EARGF(usage()));
		break;
	}ARGEND

	fmtinstall('T', typefmt);