History

remux video streams as IVF

Sigrid Haflínudóttir committed 6 years ago

Commit ed803b21 parent f8e5a164 files · +371 −162Browse files

Unified · Split

4 files
  1. .gitignore +2 −0
  2. README.md +3 −1
  3. iso.c +364 −156
  4. mkfile +2 −5
.gitignore+2−0
@@ -0,0 +1,2 @@
1+[a0125678vqki].out
2+*.[o0125678vqki]
README.md+3−1
@@ -1,4 +1,6 @@
1−# mp4
1+# mcfs
2+
3+Multimedia container file system.
24
35 Someday this might end up as a 9p filesystem for various video
46 container formats so other programs (vidya players) can identify
iso.c+364−156
@@ -4,6 +4,7 @@ · 3 unmodified lines
44
55 typedef struct Audio Audio;
66 typedef struct Box Box;
7+typedef struct Moof Moof;
78 typedef struct RunSample RunSample;
89 typedef struct SampleToChunk SampleToChunk;
910 typedef struct Track Track;
@@ -139,6 +140,11 @@ struct Box { · 129 unmodified lines
139140 u32int handlertype;
140141 char *name;
141142 }hdlr;
143+
144+ struct {
145+ int id;
146+ int flags;
147+ }esds;
142148 };
143149 };
144150
@@ -147,6 +153,7 @@ struct RunSample { · 2 unmodified lines
147153 u32int size;
148154 u32int flags;
149155 vlong timeoffset;
156+ vlong offset;
150157 };
151158
152159 struct SampleToChunk {
@@ -155,30 +162,12 @@ struct SampleToChunk { · 2 unmodified lines
155162 u32int sdt;
156163 };
157164
158−struct Track {
159− u32int handlertype;
160−
161− u64int *chunkoffset;
162− u32int numchunks;
163−
164− u32int samplesizeeach;
165− u32int *samplesize;
166− u32int numsamples;
167−
168− SampleToChunk *stc;
169− u32int numstc;
170−
171− Audio audio;
172− Video video;
173−
174− int id;
175−};
176−
177165 enum {
178166 HandlerVideo = 0x76696465u,
179167 HandlerAudio = 0x736f756eu,
180168
181169 FmtMp4a = 0x6d703461u,
170+ FmtAv01 = 0x61763031u,
182171
183172 BoxUuid = 0x75756964u,
184173 BoxFtyp = 0x66747970u,
@@ -230,6 +219,36 @@ enum { · 45 unmodified lines
230219
231220 #define eBread(sz, e) if(Bread(f, d, (sz)) != (sz)){ werrstr(e); goto err; }
232221
222+struct Moof {
223+ Box;
224+ Box mfhd;
225+ Box tfhd;
226+ Box trun;
227+};
228+
229+struct Track {
230+ u32int handlertype;
231+ u32int timescale;
232+
233+ u64int *chunkoffset;
234+ u32int numchunks;
235+
236+ u32int samplesizeeach;
237+ u32int *samplesize;
238+ u32int numsamples;
239+
240+ SampleToChunk *stc;
241+ u32int numstc;
242+
243+ Moof *moof;
244+ int nmoof;
245+
246+ Audio audio;
247+ Video video;
248+
249+ int id;
250+};
251+
233252 static int dflag;
234253 static int dind;
235254 static u32int defsamplesize;
@@ -237,6 +256,9 @@ static u32int defsamplesize; · 1 unmodified line
237256 static Track track;
238257 static Track *tracks;
239258 static int ntracks;
259+static Biobuf stderr;
260+
261+static Moof moof;
240262
241263 static int parsebox(Biobuf *f, Box *b, int *eof);
242264
@@ -267,40 +289,40 @@ printbox(Box *b) · 24 unmodified lines
267289 if(dflag == 0)
268290 return;
269291
270− fprint(2, "%.*s%T\n", dind, ind, b->type);
292+ Bprint(&stderr, "%.*s%T\n", dind, ind, b->type);
271293
272294 /* full box */
273295 if(isfullbox(b)){
274− fprint(2, "\t%.*sversion\t%d\n", dind, ind, b->version);
275− fprint(2, "\t%.*sflags\t0x%ux\n", dind, ind, b->flags);
296+ Bprint(&stderr, "\t%.*sversion\t%d\n", dind, ind, b->version);
297+ Bprint(&stderr, "\t%.*sflags\t0x%ux\n", dind, ind, b->flags);
276298 }
277299 if(dflag > 1){
278− fprint(2, "\t%.*soffset\t%zd\n", dind, ind, b->offset);
279− fprint(2, "\t%.*sdstart\t%zd\n", dind, ind, b->dstart);
280− fprint(2, "\t%.*sdsize\t%zd\n", dind, ind, b->dsz);
300+ Bprint(&stderr, "\t%.*soffset\t%zd\n", dind, ind, b->offset);
301+ Bprint(&stderr, "\t%.*sdstart\t%zd\n", dind, ind, b->dstart);
302+ Bprint(&stderr, "\t%.*sdsize\t%zd\n", dind, ind, b->dsz);
281303 }
282304
283305 if(b->type == BoxFtyp){
284− fprint(2, "\t%.*sbrand\t%T\n", dind, ind, b->ftyp.brand);
285− fprint(2, "\t%.*sversion\t%d\n", dind, ind, b->ftyp.version);
286− fprint(2, "\t%.*scompat", dind, ind);
306+ Bprint(&stderr, "\t%.*sbrand\t%T\n", dind, ind, b->ftyp.brand);
307+ Bprint(&stderr, "\t%.*sversion\t%d\n", dind, ind, b->ftyp.version);
308+ Bprint(&stderr, "\t%.*scompat", dind, ind);
287309 for(i = 0; i < b->ftyp.ncompat; i++)
288− fprint(2, "\t%.*s%T", dind, ind, b->ftyp.compat[i]);
289− fprint(2, "\n");
310+ Bprint(&stderr, "\t%.*s%T", dind, ind, b->ftyp.compat[i]);
311+ Bprint(&stderr, "\n");
290312 }else if(b->type == BoxMdhd){
291− fprint(2, "\t%.*screation\t%zd\n", dind, ind, b->mdhd.creation);
292− fprint(2, "\t%.*smodification\t%zd\n", dind, ind, b->mdhd.modification);
293− fprint(2, "\t%.*stimescale\t%ud\n", dind, ind, b->mdhd.timescale);
294− fprint(2, "\t%.*sduration\t%zd\n", dind, ind, b->mdhd.duration);
313+ Bprint(&stderr, "\t%.*screation\t%zd\n", dind, ind, b->mdhd.creation);
314+ Bprint(&stderr, "\t%.*smodification\t%zd\n", dind, ind, b->mdhd.modification);
315+ Bprint(&stderr, "\t%.*stimescale\t%ud\n", dind, ind, b->mdhd.timescale);
316+ Bprint(&stderr, "\t%.*sduration\t%zd\n", dind, ind, b->mdhd.duration);
295317 }else if(b->type == BoxMvhd){
296− fprint(2, "\t%.*screation\t%zd\n", dind, ind, b->mvhd.creation);
297− fprint(2, "\t%.*smodification\t%zd\n", dind, ind, b->mvhd.modification);
298− fprint(2, "\t%.*stimescale\t%ud\n", dind, ind, b->mvhd.timescale);
299− fprint(2, "\t%.*sduration\t%zd\n", dind, ind, b->mvhd.duration);
300− fprint(2, "\t%.*srate\t0x%ux\n", dind, ind, b->mvhd.rate);
301− fprint(2, "\t%.*svolume\t0x%ux\n", dind, ind, b->mvhd.volume);
302− fprint(2, "\t%.*snexttrack\t0x%ux\n", dind, ind, b->mvhd.nexttrack);
303− fprint(2, "\t%.*smatrix\t0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux\n", dind, ind,
318+ Bprint(&stderr, "\t%.*screation\t%zd\n", dind, ind, b->mvhd.creation);
319+ Bprint(&stderr, "\t%.*smodification\t%zd\n", dind, ind, b->mvhd.modification);
320+ Bprint(&stderr, "\t%.*stimescale\t%ud\n", dind, ind, b->mvhd.timescale);
321+ Bprint(&stderr, "\t%.*sduration\t%zd\n", dind, ind, b->mvhd.duration);
322+ Bprint(&stderr, "\t%.*srate\t0x%ux\n", dind, ind, b->mvhd.rate);
323+ Bprint(&stderr, "\t%.*svolume\t0x%ux\n", dind, ind, b->mvhd.volume);
324+ Bprint(&stderr, "\t%.*snexttrack\t0x%ux\n", dind, ind, b->mvhd.nexttrack);
325+ Bprint(&stderr, "\t%.*smatrix\t0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux 0x%ux\n", dind, ind,
304326 b->mvhd.matrix[0],
305327 b->mvhd.matrix[1],
306328 b->mvhd.matrix[2],
@@ -312,99 +334,99 @@ printbox(Box *b) · 5 unmodified lines
312334 b->mvhd.matrix[8]
313335 );
314336 }else if(b->type == BoxTrex){
315− fprint(2, "\t%.*strackid\t0x%ux\n", dind, ind, b->trex.trackid);
316− fprint(2, "\t%.*sdefsample\n", dind, ind);
317− fprint(2, "\t\t%.*sdescrindex\t0x%ux\n", dind, ind, b->trex.defsample.descrindex);
318− fprint(2, "\t\t%.*sduration\t%ud\n", dind, ind, b->trex.defsample.duration);
319− fprint(2, "\t\t%.*ssize\t0x%ux\n", dind, ind, b->trex.defsample.size);
320− fprint(2, "\t\t%.*sflags\t0x%ux\n", dind, ind, b->trex.defsample.flags);
337+ Bprint(&stderr, "\t%.*strackid\t0x%ux\n", dind, ind, b->trex.trackid);
338+ Bprint(&stderr, "\t%.*sdefsample\n", dind, ind);
339+ Bprint(&stderr, "\t\t%.*sdescrindex\t0x%ux\n", dind, ind, b->trex.defsample.descrindex);
340+ Bprint(&stderr, "\t\t%.*sduration\t%ud\n", dind, ind, b->trex.defsample.duration);
341+ Bprint(&stderr, "\t\t%.*ssize\t0x%ux\n", dind, ind, b->trex.defsample.size);
342+ Bprint(&stderr, "\t\t%.*sflags\t0x%ux\n", dind, ind, b->trex.defsample.flags);
321343 }else if(b->type == BoxMfhd){
322− fprint(2, "\t%.*sseqnumber\t%ud\n", dind, ind, b->mfhd.seqnumber);
344+ Bprint(&stderr, "\t%.*sseqnumber\t%ud\n", dind, ind, b->mfhd.seqnumber);
323345 }else if(b->type == BoxTfhd){
324− fprint(2, "\t%.*strackid\t0x%ux\n", dind, ind, b->tfhd.trackid);
346+ Bprint(&stderr, "\t%.*strackid\t%d\n", dind, ind, b->tfhd.trackid);
325347 if(b->flags & 1)
326− fprint(2, "\t%.*sbaseoffset\t%zd\n", dind, ind, b->tfhd.baseoffset);
327− fprint(2, "\t%.*sdefsample\n", dind, ind);
348+ Bprint(&stderr, "\t%.*sbaseoffset\t%zd\n", dind, ind, b->tfhd.baseoffset);
349+ Bprint(&stderr, "\t%.*sdefsample\n", dind, ind);
328350 if(b->flags & 2)
329− fprint(2, "\t\t%.*sdescrindex\t0x%ux\n", dind, ind, b->tfhd.defsample.descrindex);
351+ Bprint(&stderr, "\t\t%.*sdescrindex\t0x%ux\n", dind, ind, b->tfhd.defsample.descrindex);
330352 if(b->flags & 8)
331− fprint(2, "\t\t%.*sduration\t%ud\n", dind, ind, b->tfhd.defsample.duration);
353+ Bprint(&stderr, "\t\t%.*sduration\t%ud\n", dind, ind, b->tfhd.defsample.duration);
332354 if(b->flags & 16)
333− fprint(2, "\t\t%.*ssize\t0x%ux\n", dind, ind, b->tfhd.defsample.size);
355+ Bprint(&stderr, "\t\t%.*ssize\t0x%ux\n", dind, ind, b->tfhd.defsample.size);
334356 if(b->flags & 32)
335− fprint(2, "\t\t%.*sflags\t0x%ux\n", dind, ind, b->tfhd.defsample.flags);
357+ Bprint(&stderr, "\t\t%.*sflags\t0x%ux\n", dind, ind, b->tfhd.defsample.flags);
336358 if(b->flags & 0x10000)
337− fprint(2, "\t%.*sduration is empty\n", dind, ind);
359+ Bprint(&stderr, "\t%.*sduration is empty\n", dind, ind);
338360 if(b->flags & 0x20000)
339− fprint(2, "\t%.*sdefault base is moof\n", dind, ind);
361+ Bprint(&stderr, "\t%.*sdefault base is moof\n", dind, ind);
340362 }else if(b->type == BoxTfdt){
341− fprint(2, "\t%.*sdecodetime\t%zd\n", dind, ind, b->tfdt.decodetime);
363+ Bprint(&stderr, "\t%.*sdecodetime\t%zd\n", dind, ind, b->tfdt.decodetime);
342364 }else if(b->type == BoxTrun){
343− fprint(2, "\t%.*ssamplecount\t%ud\n", dind, ind, b->trun.samplecount);
365+ Bprint(&stderr, "\t%.*ssamplecount\t%ud\n", dind, ind, b->trun.samplecount);
344366 if(b->flags & 1)
345− fprint(2, "\t%.*sdataoffset\t%d\n", dind, ind, b->trun.dataoffset);
367+ Bprint(&stderr, "\t%.*sdataoffset\t%d\n", dind, ind, b->trun.dataoffset);
346368 if(b->flags & 2)
347− fprint(2, "\t%.*sfirstsampleflags\t0x%ux\n", dind, ind, b->trun.firstsampleflags);
369+ Bprint(&stderr, "\t%.*sfirstsampleflags\t0x%ux\n", dind, ind, b->trun.firstsampleflags);
348370 for(u = 0; dflag > 1 && u < b->trun.samplecount; u++){
349− fprint(2, "\t%.*ssamples[%zd]\n", dind, ind, u);
350− if(b->flags & 0x100)
351− fprint(2, "\t\t%.*sduration\t%ud\n", dind, ind, b->trun.samples[u].duration);
352− if(b->flags & 0x200)
353− fprint(2, "\t\t%.*ssize\t%ud\n", dind, ind, b->trun.samples[u].size);
354− if(b->flags & 0x400)
355− fprint(2, "\t\t%.*sflags\t0x%ux\n", dind, ind, b->trun.samples[u].flags);
371+ Bprint(&stderr, "\t%.*ssamples[%zd]\n", dind, ind, u);
372+ Bprint(&stderr, "\t\t%.*sduration\t%ud\n", dind, ind, b->trun.samples[u].duration);
373+ Bprint(&stderr, "\t\t%.*ssize\t%ud\n", dind, ind, b->trun.samples[u].size);
374+ Bprint(&stderr, "\t\t%.*sflags\t0x%ux\n", dind, ind, b->trun.samples[u].flags);
356375 if(b->flags & 0x800)
357− fprint(2, "\t\t%.*stimeoffset\t%zd\n", dind, ind, b->trun.samples[u].timeoffset);
376+ Bprint(&stderr, "\t\t%.*stimeoffset\t%zd\n", dind, ind, b->trun.samples[u].timeoffset);
358377 }
359378 }else if(b->type == BoxStsd){
360− fprint(2, "\t%.*sentry_count\t%ud\n", dind, ind, b->stsd.entrycount);
379+ Bprint(&stderr, "\t%.*sentry_count\t%ud\n", dind, ind, b->stsd.entrycount);
361380 if(b->stsd.video.format != 0){
362− fprint(2, "\t\t%.*svideo\t%T\n", dind, ind, b->stsd.video.format);
363− fprint(2, "\t\t\t%.*swidth\t%d\n", dind, ind, b->stsd.video.width);
364− fprint(2, "\t\t\t%.*sheight\t%d\n", dind, ind, b->stsd.video.height);
381+ Bprint(&stderr, "\t\t%.*svideo\t%T\n", dind, ind, b->stsd.video.format);
382+ Bprint(&stderr, "\t\t\t%.*swidth\t%d\n", dind, ind, b->stsd.video.width);
383+ Bprint(&stderr, "\t\t\t%.*sheight\t%d\n", dind, ind, b->stsd.video.height);
365384 }
366385 if(b->stsd.audio.format != 0){
367− fprint(2, "\t\t%.*saudio\t%T\n", dind, ind, b->stsd.audio.format);
368− fprint(2, "\t\t\t%.*schannels\t%d\n", dind, ind, b->stsd.audio.channels);
369− fprint(2, "\t\t\t%.*ssample_rate\t%d\n", dind, ind, b->stsd.audio.samplerate);
386+ Bprint(&stderr, "\t\t%.*saudio\t%T\n", dind, ind, b->stsd.audio.format);
387+ Bprint(&stderr, "\t\t\t%.*schannels\t%d\n", dind, ind, b->stsd.audio.channels);
388+ Bprint(&stderr, "\t\t\t%.*ssample_rate\t%d\n", dind, ind, b->stsd.audio.samplerate);
370389 }
371390 }else if(b->type == BoxStts){
372− fprint(2, "\t%.*sentry_count\t%ud\n", dind, ind, b->stts.entrycount);
391+ Bprint(&stderr, "\t%.*sentry_count\t%ud\n", dind, ind, b->stts.entrycount);
373392 }else if(b->type == BoxStss){
374− fprint(2, "\t%.*sentry_count\t%ud\n", dind, ind, b->stss.entrycount);
393+ Bprint(&stderr, "\t%.*sentry_count\t%ud\n", dind, ind, b->stss.entrycount);
375394 }else if(b->type == BoxStsc){
376− fprint(2, "\t%.*sentry_count\t%ud\n", dind, ind, b->stss.entrycount);
395+ Bprint(&stderr, "\t%.*sentry_count\t%ud\n", dind, ind, b->stss.entrycount);
377396 for(u = 0; dflag > 1 && u < b->stsc.entrycount; u++){
378− fprint(2, "\t%.*sentry[%zd]\n", dind, ind, u);
379− fprint(2, "\t\t%.*sfirst_chunk\t%ud\n", dind, ind, b->stsc.entry[u].firstchunk);
380− fprint(2, "\t\t%.*ssamples_per_chunk\t%ud\n", dind, ind, b->stsc.entry[u].samplesperchunk);
381− fprint(2, "\t\t%.*ssample_description_table\t%ud\n", dind, ind, b->stsc.entry[u].sdt);
397+ Bprint(&stderr, "\t%.*sentry[%zd]\n", dind, ind, u);
398+ Bprint(&stderr, "\t\t%.*sfirst_chunk\t%ud\n", dind, ind, b->stsc.entry[u].firstchunk);
399+ Bprint(&stderr, "\t\t%.*ssamples_per_chunk\t%ud\n", dind, ind, b->stsc.entry[u].samplesperchunk);
400+ Bprint(&stderr, "\t\t%.*ssample_description_table\t%ud\n", dind, ind, b->stsc.entry[u].sdt);
382401 }
383402 }else if(b->type == BoxStsz){
384− fprint(2, "\t%.*ssample_size\t%ud\n", dind, ind, b->stsz.samplesizeeach);
385− fprint(2, "\t%.*ssample_count\t%ud\n", dind, ind, b->stsz.samplecount);
403+ Bprint(&stderr, "\t%.*ssample_size\t%ud\n", dind, ind, b->stsz.samplesizeeach);
404+ Bprint(&stderr, "\t%.*ssample_count\t%ud\n", dind, ind, b->stsz.samplecount);
386405 if(dflag > 1 && b->stsz.samplesizeeach == 0){
387406 for(u = 0; u < b->stsz.samplecount; u++)
388− fprint(2, "\t%.*ssamplesize[%zd]\t%ud\n", dind, ind, u, b->stsz.samplesize[u]);
407+ Bprint(&stderr, "\t%.*ssamplesize[%zd]\t%ud\n", dind, ind, u, b->stsz.samplesize[u]);
389408 }
390409 }else if(b->type == BoxTkhd){
391− fprint(2, "\t%.*screation_time\t%zd\n", dind, ind, b->tkhd.creattime);
392− fprint(2, "\t%.*smodification_timetime\t%zd\n", dind, ind, b->tkhd.modtime);
393− fprint(2, "\t%.*strack_id\t%ud\n", dind, ind, b->tkhd.trackid);
394− fprint(2, "\t%.*sduration\t%zd\n", dind, ind, b->tkhd.duration);
395− fprint(2, "\t%.*swidth\t%ud\n", dind, ind, b->tkhd.width);
396− fprint(2, "\t%.*sheight\t%ud\n", dind, ind, b->tkhd.height);
410+ Bprint(&stderr, "\t%.*screation_time\t%zd\n", dind, ind, b->tkhd.creattime);
411+ Bprint(&stderr, "\t%.*smodification_time\t%zd\n", dind, ind, b->tkhd.modtime);
412+ Bprint(&stderr, "\t%.*strack_id\t%ud\n", dind, ind, b->tkhd.trackid);
413+ Bprint(&stderr, "\t%.*sduration\t%zd\n", dind, ind, b->tkhd.duration);
414+ Bprint(&stderr, "\t%.*swidth\t%ud\n", dind, ind, b->tkhd.width);
415+ Bprint(&stderr, "\t%.*sheight\t%ud\n", dind, ind, b->tkhd.height);
397416 }else if(b->type == BoxHdlr){
398− fprint(2, "\t%.*shandler_type\t%T\n", dind, ind, b->hdlr.handlertype);
399− fprint(2, "\t%.*sname\t%s\n", dind, ind, b->hdlr.name);
417+ Bprint(&stderr, "\t%.*shandler_type\t%T\n", dind, ind, b->hdlr.handlertype);
418+ Bprint(&stderr, "\t%.*sname\t%s\n", dind, ind, b->hdlr.name);
400419 }else if(b->type == BoxStco || b->type == BoxCo64){
401− fprint(2, "\t%.*sentry_count\t%ud\n", dind, ind, b->stss.entrycount);
420+ Bprint(&stderr, "\t%.*sentry_count\t%ud\n", dind, ind, b->stss.entrycount);
402421 for(u = 0; dflag > 1 && u < b->stco_co64.entrycount; u++)
403− fprint(2, "\t%.*schunkoffset[%zd]\t%zd\n", dind, ind, u, b->stco_co64.chunkoffset[u]);
422+ Bprint(&stderr, "\t%.*schunkoffset[%zd]\t%zd\n", dind, ind, u, b->stco_co64.chunkoffset[u]);
423+ }else if(b->type == BoxEsds){
424+ Bprint(&stderr, "\t%.*sid\t%d\n", dind, ind, b->esds.id);
425+ Bprint(&stderr, "\t%.*sflags\t0x%x\n", dind, ind, b->esds.flags);
404426 }else if(dflag < 2){
405− fprint(2, "\t%.*soffset\t%zd\n", dind, ind, b->offset);
406− fprint(2, "\t%.*sdstart\t%zd\n", dind, ind, b->dstart);
407− fprint(2, "\t%.*sdsize\t%zd\n", dind, ind, b->dsz);
427+ Bprint(&stderr, "\t%.*soffset\t%zd\n", dind, ind, b->offset);
428+ Bprint(&stderr, "\t%.*sdstart\t%zd\n", dind, ind, b->dstart);
429+ Bprint(&stderr, "\t%.*sdsize\t%zd\n", dind, ind, b->dsz);
408430 }
409431 }
410432
@@ -415,6 +437,38 @@ addtrack(void) · 4 unmodified lines
415437 memmove(&tracks[ntracks++], &track, sizeof(track));
416438 }
417439
440+static Track *
441+gettrack(int id)
442+{
443+ Track *t;
444+ int i;
445+
446+ for(t = tracks, i = 0; i < ntracks && t->id != id; i++, t++){
447+ fprint(2, "%d != %d\n", t->id, id);
448+ }
449+ if(i >= ntracks){
450+ werrstr("no track %d", id);
451+ t = nil;
452+ }
453+
454+ return t;
455+}
456+
457+static void
458+addtrun(Box *trun)
459+{
460+ Track *t;
461+ Moof *m;
462+
463+ if((t = gettrack(moof.tfhd.tfhd.trackid)) == nil)
464+ sysfatal("trun without a track");
465+
466+ t->moof = realloc(t->moof, (t->nmoof+1)*sizeof(Moof));
467+ m = &t->moof[t->nmoof++];
468+ memmove(&moof.trun, trun, sizeof(moof.trun));
469+ memmove(m, &moof, sizeof(moof));
470+}
471+
418472 static int srate2mpeg4fi[] = {
419473 96000,
420474 88200,
@@ -432,51 +486,14 @@ static int srate2mpeg4fi[] = { · 11 unmodified lines
432486 };
433487
434488 static int
435−dumptrack(Biobuf *f, int id)
489+dumpstc(Biobuf *f, Biobuf *out, Track *t, u8int *frame)
436490 {
437491 SampleToChunk *stc;
438492 u32int si, ch, nextch;
439493 u32int samplelast, sample, rawsz, samplesz;
440494 u64int o, wo;
441− int i;
442495 u8int *raw;
443− Biobuf out;
444− Track *t;
445− u8int frame[7];
446−
447− for(t = tracks, i = 0; i < ntracks && t->id != id; i++, t++);
448− if(i >= ntracks){
449− werrstr("no track %d", id);
450− return -1;
451− }
452496
453− fprint(
454− 2,
455− "track %d: handler=%T numstc=%ud chunks=%ud samples=%ud\n", t->id, t->handlertype, t->numstc, t->numchunks, t->numsamples
456− );
457− if(t->audio.format != 0){
458− fprint(2, "audio: format=%T channels=%d samplerate=%d\n", t->audio.format, t->audio.channels, t->audio.samplerate);
459− if(t->audio.format == FmtMp4a){
460− for(i = 0; i < nelem(srate2mpeg4fi) && srate2mpeg4fi[i] != t->audio.samplerate; i++);
461− if(i >= nelem(srate2mpeg4fi)){
462− werrstr("audio: mpeg4: invalid sample rate %d", t->audio.samplerate);
463− return -1;
464− }
465− frame[0] = 0xff; /* syncword */
466− frame[1] = 0xf1; /* syncword, mpeg4, no crc */
467− frame[2] = 1<<6 | i<<2 | t->audio.channels>>2; /* AAC(LC)??? FIXME, frequency index, channels */
468− }else{
469− werrstr("audio: unknown format %T\n", t->audio.format);
470− return -1;
471− }
472− }
473− if(t->video.format != 0){
474− fprint(2, "video: format=%T resolution=%dx%d\n", t->video.format, t->video.width, t->video.height);
475− //werrstr("video: unknown format %T", t->video.format);
476− //return -1;
477− }
478−
479− Binit(&out, 1, OWRITE);
480497 raw = nil;
481498 rawsz = 0;
482499 sample = samplelast = 0;
@@ -515,14 +532,14 @@ dumptrack(Biobuf *f, int id) · 32 unmodified lines
515532 frame[5] = (samplesz&7)<<5 | 0x1f; /* frame length, fullness */
516533 frame[6] = 0xfc; /* fullness, number of frames */
517534 samplesz -= 7;
518− if(Bwrite(&out, frame, 7) != 7){ /* EOF */
535+ if(Bwrite(out, frame, 7) != 7){ /* EOF */
519536 werrstr("eof");
520537 break;
521538 }
522539 wo += 7;
523540 o += 7;
524541 }
525− if(Bwrite(&out, raw, samplesz) != samplesz){ /* EOF? */
542+ if(Bwrite(out, raw, samplesz) != samplesz){ /* EOF? */
526543 werrstr("eof");
527544 break;
528545 }
@@ -532,10 +549,167 @@ dumptrack(Biobuf *f, int id) · 3 unmodified lines
532549 samplelast = sample;
533550 }
534551 }
535− Bterm(&out);
536552 free(raw);
537553
538554 return 0;
555+}
556+
557+static int
558+dumptrun(Biobuf *f, Biobuf *out, Track *t, u8int *frame)
559+{
560+ int i, j;
561+ u64int ts;
562+ u8int *raw;
563+ int maxsz;
564+ RunSample *s;
565+ Moof *m;
566+
567+ USED(frame);
568+
569+ if(t->video.format == 0)
570+ sysfatal("trun dump only works with IVF atm"); /* FIXME */
571+
572+ ts = 0;
573+ maxsz = 0;
574+ raw = nil;
575+ for(i = 0, m = t->moof; i < t->nmoof; i++, m++){
576+ for(j = 0; j < m->trun.trun.samplecount; j++){
577+ s = &m->trun.trun.samples[j];
578+ if(12 + s->size > maxsz){
579+ maxsz = 12 + s->size;
580+ raw = realloc(raw, maxsz);
581+ }
582+ raw[0] = s->size;
583+ raw[1] = s->size >> 8;
584+ raw[2] = s->size >> 16;
585+ raw[3] = s->size >> 24;
586+ raw[4] = ts;
587+ raw[5] = ts >> 8;
588+ raw[6] = ts >> 16;
589+ raw[7] = ts >> 24;
590+ raw[8] = ts >> 32;
591+ raw[9] = ts >> 40;
592+ raw[10] = ts >> 48;
593+ raw[11] = ts >> 56;
594+ if(Bseek(f, s->offset, 0) != s->offset){
595+ werrstr("couldn't seek to offset %zd", s->offset);
596+ return -1;
597+ }
598+ if(Bread(f, raw+12, s->size) != s->size){
599+ werrstr("couldn't read sample (%d bytes)", s->size);
600+ return -1;
601+ }
602+ if(Bwrite(out, raw, 12 + s->size) != 12 + s->size) /* eof? */
603+ break;
604+ ts += s->duration; /* sample's "time offset" is ignored here */
605+ }
606+ }
607+
608+ return 0;
609+}
610+
611+static int
612+dumptrack(Biobuf *f, int id)
613+{
614+ int i, j, res;
615+ Biobuf out;
616+ u64int dur;
617+ Track *t;
618+ Moof *m;
619+ u8int frame[0x20];
620+
621+ if((t = gettrack(id)) == nil)
622+ return -1;
623+
624+ if(dflag)
625+ Bprint(&stderr, "track %d: handler=%T ", t->id, t->handlertype);
626+ if(t->numstc > 0){
627+ if(dflag)
628+ Bprint(&stderr, "numstc=%ud chunks=%ud samples=%ud\n", t->numstc, t->numchunks, t->numsamples);
629+ }else if(t->nmoof > 0){
630+ if(dflag)
631+ Bprint(&stderr, "numtrun: %d\n", t->nmoof);
632+ }else{
633+ if(dflag)
634+ Bprint(&stderr, "no samples\n");
635+ werrstr("track %d has no samples", t->id);
636+ return -1;
637+ }
638+
639+ Binit(&out, 1, OWRITE);
640+
641+ if(t->audio.format != 0){
642+ Bprint(&stderr, "audio: format=%T channels=%d samplerate=%d\n", t->audio.format, t->audio.channels, t->audio.samplerate);
643+ if(t->audio.format == FmtMp4a){
644+ for(i = 0; i < nelem(srate2mpeg4fi) && srate2mpeg4fi[i] != t->audio.samplerate; i++);
645+ if(i >= nelem(srate2mpeg4fi)){
646+ werrstr("audio: mpeg4: invalid sample rate %d", t->audio.samplerate);
647+ return -1;
648+ }
649+ frame[0] = 0xff; /* syncword */
650+ frame[1] = 0xf1; /* syncword, mpeg4, no crc */
651+ frame[2] = 1<<6 | i<<2 | t->audio.channels>>2; /* AAC(LC)??? FIXME, frequency index, channels */
652+ }else{
653+ werrstr("audio: unknown format %T\n", t->audio.format);
654+ return -1;
655+ }
656+ }else if(t->video.format != 0){
657+ Bprint(&stderr, "video: format=%T resolution=%dx%d\n", t->video.format, t->video.width, t->video.height);
658+ /* video is remuxed into IVF */
659+ memset(frame, 0, 0x20);
660+ memmove(frame, "DKIF", 4);
661+ frame[4] = 0;
662+ frame[5] = 0;
663+ frame[6] = 0x20;
664+ frame[7] = 0;
665+ if(t->video.format == FmtAv01){
666+ memmove(frame+8, "AV01", 4);
667+ frame[12] = t->video.width;
668+ frame[13] = t->video.width >> 8;
669+ frame[14] = t->video.height;
670+ frame[15] = t->video.height >> 8;
671+ /* timebase denum */
672+ frame[16] = t->timescale;
673+ frame[17] = t->timescale >> 8;
674+ frame[18] = t->timescale >> 16;
675+ frame[19] = t->timescale >> 24;
676+ /* timebase num */
677+ frame[20] = 1;
678+ frame[21] = 0;
679+ frame[22] = 0;
680+ frame[23] = 0;
681+ /* FIXME is it a "number of frames" or "total duration?" */
682+ dur = 0;
683+ for(i = 0, m = t->moof; i < t->nmoof; i++, m++){
684+ for(j = 0; j < m->trun.trun.samplecount; j++){
685+ dur += m->trun.trun.samples[j].duration;
686+ }
687+ }
688+ frame[24] = dur;
689+ frame[25] = dur >> 8;
690+ frame[26] = dur >> 16;
691+ frame[27] = dur >> 24;
692+ frame[28] = dur >> 32; /* FIXME is it 64 bits? */
693+ frame[29] = dur >> 40;
694+ frame[30] = dur >> 48;
695+ frame[31] = dur >> 56;
696+
697+ Bwrite(&out, frame, 0x20);
698+ }else{
699+ werrstr("video: unknown format %T", t->video.format);
700+ return -1;
701+ }
702+ }
703+
704+ res = -1;
705+ if(t->numstc > 0)
706+ res = dumpstc(f, &out, t, frame);
707+ else if(t->nmoof > 0)
708+ res = dumptrun(f, &out, t, frame);
709+
710+ Bterm(&out);
711+
712+ return res;
539713 };
540714
541715 int
@@ -565,7 +739,7 @@ sampleentry(Biobuf *f, Box *b, u32int fmt, int n) · 23 unmodified lines
565739 memmove(&track.audio, &b->stsd.audio, sizeof(Audio));
566740 /* FIXME do we care about the rest? */
567741 }else{
568− fprint(2, "SampleEntry: unknown handler type %T\n", track.handlertype);
742+ Bprint(&stderr, "SampleEntry: unknown handler type %T\n", track.handlertype);
569743 }
570744
571745 return n;
@@ -579,8 +753,8 @@ parseboxdata(Biobuf *f, Box *b) · 7 unmodified lines
579753 u8int d[128], *p;
580754 Box inner;
581755 int i, n, eof;
582− s32int s32i;
583− u64int u;
756+ u64int u, off;
757+ RunSample *s;
584758
585759 if(b->type == BoxFtyp){
586760 eBread(8, "brand and version");
@@ -601,6 +775,10 @@ parseboxdata(Biobuf *f, Box *b) · 14 unmodified lines
601775 b->type == BoxMdia || b->type == BoxMinf || b->type == BoxStbl ||
602776 b->type == BoxMoof || b->type == BoxTraf || b->type == BoxEdts ||
603777 b->type == BoxDinf){
778+ if(b->type == BoxMoof){
779+ memset(&moof, 0, sizeof(moof));
780+ memmove(&moof, b, sizeof(Box));
781+ }
604782 printbox(b);
605783 dind++;
606784 for(;;){
@@ -616,6 +794,8 @@ parseboxdata(Biobuf *f, Box *b) · 9 unmodified lines
616794 memset(&track, 0, sizeof(track));
617795 }
618796 dind--;
797+ if(b->type == BoxMoof)
798+ memset(&moof, 0, sizeof(moof));
619799 }else if(b->type == BoxMdhd){
620800 n = b->version == 0 ? 16 : 28;
621801 eBread(n, "short read");
@@ -632,6 +812,7 @@ parseboxdata(Biobuf *f, Box *b) · 10 unmodified lines
632812 }
633813
634814 b->mdhd.timescale = bu32(p); p += 4;
815+ track.timescale = b->mdhd.timescale; /* it's used for IVF timebase */
635816
636817 b->mdhd.duration = bu32(p); p += 4;
637818 if(b->version == 1){
@@ -683,6 +864,7 @@ parseboxdata(Biobuf *f, Box *b) · 45 unmodified lines
683864 }else if(b->type == BoxMfhd){
684865 eBread(4, "short read");
685866 b->mfhd.seqnumber = bu32(d);
867+ memmove(&moof.mfhd, b, sizeof(*b));
686868 printbox(b);
687869 }else if(b->type == BoxTfhd){
688870 eBread(4, "track_id");
@@ -708,6 +890,7 @@ parseboxdata(Biobuf *f, Box *b) · 19 unmodified lines
708890 eBread(4, "default_sample_flags");
709891 b->tfhd.defsample.flags = bu32(d);
710892 }
893+ memmove(&moof.tfhd, b, sizeof(*b));
711894 printbox(b);
712895 }else if(b->type == BoxTfdt){
713896 if(b->version == 1){
@@ -731,32 +914,53 @@ parseboxdata(Biobuf *f, Box *b) · 17 unmodified lines
731914 }
732915 /* FIXME free those */
733916 b->trun.samples = calloc(b->trun.samplecount, sizeof(RunSample));
917+ off = 0;
734918 for(u = 0; u < b->trun.samplecount; u++){
919+ s = &b->trun.samples[u];
735920 if(b->flags & 0x100){
736921 eBread(4, "sample_duration");
737− b->trun.samples[u].duration = bu32(d);
738− }
922+ s->duration = bu32(d);
923+ }else if(moof.tfhd.flags & 8)
924+ s->duration = moof.tfhd.tfhd.defsample.duration;
925+
739926 if(b->flags & 0x200){
740927 eBread(4, "sample_size");
741− b->trun.samples[u].size = bu32(d);
742− }
928+ s->size = bu32(d);
929+ }else if(moof.tfhd.flags & 16)
930+ s->size = moof.tfhd.tfhd.defsample.size;
931+
743932 if(b->flags & 0x400){
744933 eBread(4, "sample_flags");
745− b->trun.samples[u].flags = bu32(d);
746− }
934+ s->flags = bu32(d);
935+ }else if((b->flags & 4) && u == 0){
936+ // FIXME default flags???
937+ s->flags = b->trun.firstsampleflags;
938+ }else if(moof.tfhd.flags & 32)
939+ s->flags = moof.tfhd.tfhd.defsample.flags;
940+
747941 if(b->flags & 0x800){
748942 eBread(4, "sample_composition_time_offset");
749− s32i = bu32(d);
750943 if(b->version == 0)
751− b->trun.samples[u].timeoffset = bu32(d);
944+ s->timeoffset = bu32(d);
752945 else
753− b->trun.samples[u].timeoffset = s32i;
946+ s->timeoffset = (s32int)bu32(d);
754947 }
948+
949+ s->offset = b->trun.dataoffset + off;
950+ if(moof.tfhd.flags & 1)
951+ Bprint(&stderr, "tfhd has base-data-offset-present set, this isn't supported atm\n");
952+ else if(moof.tfhd.flags & 0x20000)
953+ s->offset += moof.offset + moof.tfhd.tfhd.baseoffset;
954+ else
955+ Bprint(&stderr, "couldn't calculate sample offset\n");
956+ off += s->size;
755957 }
958+ addtrun(b);
756959 printbox(b);
757960 }else if(b->type == BoxEsds){
758961 eBread(3, "es id");
759− fprint(2, "# es id: %ud\n# es flags: 0x%02x\n", bu16(d+1), d[3]);
962+ b->esds.id = bu16(d+1);
963+ b->esds.flags = d[3];
760964 printbox(b);
761965 }else if(b->type == BoxStsd){
762966 eBread(4, "entry_count");
@@ -950,7 +1154,7 @@ err: · 187 unmodified lines
9501154 static void
9511155 usage(void)
9521156 {
953− fprint(2, "usage: iso [-d] [-t TRACK] FILE\n");
1157+ Bprint(&stderr, "usage: iso [-d] [-t TRACK] FILE\n");
9541158 exits("usage");
9551159 }
9561160
@@ -975,6 +1179,8 @@ main(int argc, char **argv) · 18 unmodified lines
9751179
9761180 fmtinstall('T', typefmt);
9771181
1182+ Binit(&stderr, 2, OWRITE);
1183+
9781184 status = nil;
9791185 for(; *argv && status == nil; argv++){
9801186 if((f = Bopen(*argv, OREAD)) == nil)
@@ -992,12 +1198,14 @@ main(int argc, char **argv) · 11 unmodified lines
9921198 }
9931199
9941200 if(trackdump >= 0 && dumptrack(f, trackdump) != 0){
995− fprint(2, "%s: %r\n", *argv);
1201+ Bprint(&stderr, "%s: %r\n", *argv);
9961202 status = "dump";
9971203 }
9981204
9991205 Bterm(f);
10001206 }
10011207
1208+ Bterm(&stderr);
1209+
10021210 exits(status);
10031211 }
mkfile+2−5
@@ -1,8 +1,7 @@
11 </$objtype/mkfile
22 MAN=/sys/man/1
33
4−TARG=\
5− iso\
4+TARG=mcfs
65
76 BIN=/$objtype/bin
87
@@ -13,6 +12,4 @@ HFILES=\ · 4 unmodified lines
1312
1413 default:V: all
1514
16−</sys/src/cmd/mkmany
17−
18−install:
15+</sys/src/cmd/mkone

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t