Unified · Split
| @@ -4,6 +4,8 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | typedef struct Box Box; | 5 | typedef struct Box Box; |
| 6 | typedef struct RunSample RunSample; | 6 | typedef struct RunSample RunSample; |
| 7 | typedef struct Track Track; | ||
| 8 | typedef struct SampleToChunk SampleToChunk; | ||
| 7 | 9 | ||
| 8 | struct Box { | 10 | struct Box { |
| 9 | vlong dsz; | 11 | vlong dsz; |
| @@ -88,11 +90,7 @@ struct Box { · 78 unmodified lines | |||
| 88 | 90 | ||
| 89 | struct { | 91 | struct { |
| 90 | u32int entrycount; | 92 | u32int entrycount; |
| 91 | struct { | 93 | SampleToChunk *entry; |
| 92 | u32int firstchunk; | ||
| 93 | u32int samplesperchunk; | ||
| 94 | u32int sdt; | ||
| 95 | }*entry; | ||
| 96 | }stsc; | 94 | }stsc; |
| 97 | 95 | ||
| 98 | struct { | 96 | struct { |
| @@ -129,6 +127,25 @@ struct RunSample { · 30 unmodified lines | |||
| 129 | vlong timeoffset; | 127 | vlong timeoffset; |
| 130 | }; | 128 | }; |
| 131 | 129 | ||
| 130 | struct Track { | ||
| 131 | u64int *chunkoffset; | ||
| 132 | u32int numchunks; | ||
| 133 | |||
| 134 | u32int *samplesize; | ||
| 135 | u32int numsamples; | ||
| 136 | |||
| 137 | SampleToChunk *stc; | ||
| 138 | u32int numstc; | ||
| 139 | |||
| 140 | int id; | ||
| 141 | }; | ||
| 142 | |||
| 143 | struct SampleToChunk { | ||
| 144 | u32int firstchunk; | ||
| 145 | u32int samplesperchunk; | ||
| 146 | u32int sdt; | ||
| 147 | }; | ||
| 148 | |||
| 132 | enum { | 149 | enum { |
| 133 | BoxUuid = 0x75756964u, | 150 | BoxUuid = 0x75756964u, |
| 134 | BoxFtyp = 0x66747970u, | 151 | BoxFtyp = 0x66747970u, |
| @@ -146,6 +163,7 @@ enum { · 11 unmodified lines | |||
| 146 | BoxMinf = 0x6d696e66u, | 163 | BoxMinf = 0x6d696e66u, |
| 147 | BoxDinf = 0x64696e66u, | 164 | BoxDinf = 0x64696e66u, |
| 148 | BoxStbl = 0x7374626cu, | 165 | BoxStbl = 0x7374626cu, |
| 166 | BoxCtts = 0x63747473u, | ||
| 149 | BoxStsd = 0x73747364u, | 167 | BoxStsd = 0x73747364u, |
| 150 | BoxStts = 0x73747473u, | 168 | BoxStts = 0x73747473u, |
| 151 | BoxStsc = 0x73747363u, | 169 | BoxStsc = 0x73747363u, |
| @@ -173,15 +191,18 @@ enum { · 21 unmodified lines | |||
| 173 | b->type == BoxMfhd || b->type == BoxTfhd || b->type == BoxTfdt || b->type == BoxTrun || \ | 191 | b->type == BoxMfhd || b->type == BoxTfhd || b->type == BoxTfdt || b->type == BoxTrun || \ |
| 174 | b->type == BoxStsd || b->type == BoxStts || b->type == BoxStss || b->type == BoxTkhd || \ | 192 | b->type == BoxStsd || b->type == BoxStts || b->type == BoxStss || b->type == BoxTkhd || \ |
| 175 | b->type == BoxElst || b->type == BoxStsc || b->type == BoxStco || b->type == BoxCo64 || \ | 193 | b->type == BoxElst || b->type == BoxStsc || b->type == BoxStco || b->type == BoxCo64 || \ |
| 176 | b->type == BoxStsz \ | 194 | b->type == BoxStsz || b->type == BoxCtts \ |
| 177 | ) | 195 | ) |
| 178 | 196 | ||
| 179 | #define eBread(sz, e) if(Bread(f, d, (sz)) != (sz)){ werrstr(e); goto err; } | 197 | #define eBread(sz, e) if(Bread(f, d, (sz)) != (sz)){ werrstr(e); goto err; } |
| 180 | 198 | ||
| 181 | static int dflag; | 199 | static int dflag; |
| 182 | static int dind; | 200 | static int dind; |
| 201 | static int trackdump = -1; | ||
| 183 | static u32int defsamplesize; | 202 | static u32int defsamplesize; |
| 184 | 203 | ||
| 204 | static Track track; | ||
| 205 | |||
| 185 | static int parsebox(Biobuf *f, Box *b, int *eof); | 206 | static int parsebox(Biobuf *f, Box *b, int *eof); |
| 186 | 207 | ||
| 187 | #pragma varargck type "T" u32int | 208 | #pragma varargck type "T" u32int |
| @@ -332,6 +353,47 @@ printbox(Box *b) · 144 unmodified lines | |||
| 332 | } | 353 | } |
| 333 | } | 354 | } |
| 334 | 355 | ||
| 356 | static void | ||
| 357 | dumptrack(Biobuf *f) | ||
| 358 | { | ||
| 359 | SampleToChunk *stc; | ||
| 360 | u32int si, ch, lastch; | ||
| 361 | u32int samplelast, sample, rawsz; | ||
| 362 | vlong o; | ||
| 363 | u8int *raw; | ||
| 364 | Biobuf out; | ||
| 365 | |||
| 366 | Binit(&out, 1, OWRITE); | ||
| 367 | raw = nil; | ||
| 368 | rawsz = 0; | ||
| 369 | sample = samplelast = 0; | ||
| 370 | stc = track.stc; | ||
| 371 | for(si = 0; si < track.numstc; si++, stc++){ | ||
| 372 | lastch = si+1 < track.numstc ? stc[1].firstchunk : track.numchunks; | ||
| 373 | for(ch = stc->firstchunk-1; ch < lastch && ch < track.numchunks; ch++){ | ||
| 374 | o = track.chunkoffset[ch]; | ||
| 375 | if(Bseek(f, o, 0) != o) | ||
| 376 | sysfatal("chunk %ud: %r", ch); | ||
| 377 | for(; sample < samplelast+stc->samplesperchunk && sample < track.numsamples; sample++){ | ||
| 378 | if(track.samplesize[sample] == 0) | ||
| 379 | break; | ||
| 380 | if(rawsz < track.samplesize[sample]){ | ||
| 381 | rawsz = track.samplesize[sample] * 2; | ||
| 382 | raw = realloc(raw, rawsz); | ||
| 383 | } | ||
| 384 | if(Bread(f, raw, track.samplesize[sample]) != track.samplesize[sample]) | ||
| 385 | sysfatal("chunk %ud sample %ud size %ud: %r", ch, sample, track.samplesize[sample]); | ||
| 386 | if(Bwrite(&out, raw, track.samplesize[sample]) != track.samplesize[sample]) | ||
| 387 | exits(nil); | ||
| 388 | } | ||
| 389 | samplelast = sample; | ||
| 390 | } | ||
| 391 | } | ||
| 392 | fprint(2, "%ud samples\n", sample); | ||
| 393 | Bterm(&out); | ||
| 394 | free(raw); | ||
| 395 | }; | ||
| 396 | |||
| 335 | static int | 397 | static int |
| 336 | parseboxdata(Biobuf *f, Box *b) | 398 | parseboxdata(Biobuf *f, Box *b) |
| 337 | { | 399 | { |
| @@ -369,6 +431,17 @@ parseboxdata(Biobuf *f, Box *b) · 31 unmodified lines | |||
| 369 | if(inner.dstart+inner.dsz >= b->dstart+b->dsz) | 431 | if(inner.dstart+inner.dsz >= b->dstart+b->dsz) |
| 370 | break; | 432 | break; |
| 371 | } | 433 | } |
| 434 | if(b->type == BoxTrak){ | ||
| 435 | if(track.id == trackdump){ | ||
| 436 | u = Boffset(f); | ||
| 437 | dumptrack(f); | ||
| 438 | Bseek(f, u, 0); | ||
| 439 | } | ||
| 440 | free(track.chunkoffset); | ||
| 441 | free(track.samplesize); | ||
| 442 | free(track.stc); | ||
| 443 | memset(&track, 0, sizeof(track)); | ||
| 444 | } | ||
| 372 | dind--; | 445 | dind--; |
| 373 | }else if(b->type == BoxMvhd){ | 446 | }else if(b->type == BoxMvhd){ |
| 374 | n = b->version == 0 ? 96 : 108; | 447 | n = b->version == 0 ? 96 : 108; |
| @@ -506,7 +579,7 @@ parseboxdata(Biobuf *f, Box *b) · 131 unmodified lines | |||
| 506 | }else if(b->type == BoxStsc){ | 579 | }else if(b->type == BoxStsc){ |
| 507 | eBread(4, "entry_count"); | 580 | eBread(4, "entry_count"); |
| 508 | b->stsc.entrycount = bu32(d); | 581 | b->stsc.entrycount = bu32(d); |
| 509 | b->stsc.entry = calloc(b->stsc.entrycount, sizeof(*b->stsc.entry)); | 582 | b->stsc.entry = calloc(b->stsc.entrycount, sizeof(SampleToChunk)); |
| 510 | for(u = 0; u < b->stsc.entrycount; u++){ | 583 | for(u = 0; u < b->stsc.entrycount; u++){ |
| 511 | eBread(4, "first_chunk"); | 584 | eBread(4, "first_chunk"); |
| 512 | b->stsc.entry[u].firstchunk = bu32(d); | 585 | b->stsc.entry[u].firstchunk = bu32(d); |
| @@ -515,6 +588,8 @@ parseboxdata(Biobuf *f, Box *b) · 2 unmodified lines | |||
| 515 | eBread(4, "sample_description_table"); | 588 | eBread(4, "sample_description_table"); |
| 516 | b->stsc.entry[u].sdt = bu32(d); | 589 | b->stsc.entry[u].sdt = bu32(d); |
| 517 | } | 590 | } |
| 591 | track.numstc = b->stsc.entrycount; | ||
| 592 | track.stc = b->stsc.entry; | ||
| 518 | printbox(b); | 593 | printbox(b); |
| 519 | }else if(b->type == BoxStco || b->type == BoxCo64){ | 594 | }else if(b->type == BoxStco || b->type == BoxCo64){ |
| 520 | eBread(4, "entry_count"); | 595 | eBread(4, "entry_count"); |
| @@ -524,6 +599,8 @@ parseboxdata(Biobuf *f, Box *b) · 3 unmodified lines | |||
| 524 | eBread(b->type == BoxStco ? 4 : 8, "chunk_offset"); | 599 | eBread(b->type == BoxStco ? 4 : 8, "chunk_offset"); |
| 525 | b->stco_co64.chunkoffset[u] = b->type == BoxStco ? bu32(d) : bu64(d); | 600 | b->stco_co64.chunkoffset[u] = b->type == BoxStco ? bu32(d) : bu64(d); |
| 526 | } | 601 | } |
| 602 | track.numchunks = b->stco_co64.entrycount; | ||
| 603 | track.chunkoffset = b->stco_co64.chunkoffset; | ||
| 527 | printbox(b); | 604 | printbox(b); |
| 528 | }else if(b->type == BoxStsz){ | 605 | }else if(b->type == BoxStsz){ |
| 529 | eBread(4, "sample_size"); | 606 | eBread(4, "sample_size"); |
| @@ -536,6 +613,8 @@ parseboxdata(Biobuf *f, Box *b) · 6 unmodified lines | |||
| 536 | eBread(4, "chunk_offset"); | 613 | eBread(4, "chunk_offset"); |
| 537 | b->stsz.entrysize[u] = bu32(d); | 614 | b->stsz.entrysize[u] = bu32(d); |
| 538 | } | 615 | } |
| 616 | track.numsamples = b->stsz.samplecount; | ||
| 617 | track.samplesize = b->stsz.entrysize; | ||
| 539 | } | 618 | } |
| 540 | printbox(b); | 619 | printbox(b); |
| 541 | }else if(b->type == BoxTkhd){ | 620 | }else if(b->type == BoxTkhd){ |
| @@ -546,6 +625,7 @@ parseboxdata(Biobuf *f, Box *b) · 4 unmodified lines | |||
| 546 | b->tkhd.modtime = bu64(d); | 625 | b->tkhd.modtime = bu64(d); |
| 547 | eBread(8, "track_id"); /* skipping 4 reserved as well */ | 626 | eBread(8, "track_id"); /* skipping 4 reserved as well */ |
| 548 | b->tkhd.trackid = bu32(d); | 627 | b->tkhd.trackid = bu32(d); |
| 628 | track.id = b->tkhd.trackid; | ||
| 549 | eBread(8, "duration"); | 629 | eBread(8, "duration"); |
| 550 | b->tkhd.duration = bu64(d); | 630 | b->tkhd.duration = bu64(d); |
| 551 | }else if(b->version == 0){ | 631 | }else if(b->version == 0){ |
| @@ -555,6 +635,7 @@ parseboxdata(Biobuf *f, Box *b) · 3 unmodified lines | |||
| 555 | b->tkhd.modtime = bu32(d); | 635 | b->tkhd.modtime = bu32(d); |
| 556 | eBread(8, "track_id"); /* skipping 4 reserved as well */ | 636 | eBread(8, "track_id"); /* skipping 4 reserved as well */ |
| 557 | b->tkhd.trackid = bu32(d); | 637 | b->tkhd.trackid = bu32(d); |
| 638 | track.id = b->tkhd.trackid; | ||
| 558 | eBread(4, "duration"); | 639 | eBread(4, "duration"); |
| 559 | b->tkhd.duration = bu32(d); | 640 | b->tkhd.duration = bu32(d); |
| 560 | }else{ | 641 | }else{ |
| @@ -651,6 +732,13 @@ err: · 90 unmodified lines | |||
| 651 | return -1; | 732 | return -1; |
| 652 | } | 733 | } |
| 653 | 734 | ||
| 735 | static void | ||
| 736 | usage(void) | ||
| 737 | { | ||
| 738 | fprint(2, "usage: iso [-d] [-t TRACK] FILE\n"); | ||
| 739 | exits("usage"); | ||
| 740 | } | ||
| 741 | |||
| 654 | int | 742 | int |
| 655 | main(int argc, char **argv) | 743 | main(int argc, char **argv) |
| 656 | { | 744 | { |
| @@ -663,6 +751,9 @@ main(int argc, char **argv) · 6 unmodified lines | |||
| 663 | case 'd': | 751 | case 'd': |
| 664 | dflag = 1; | 752 | dflag = 1; |
| 665 | break; | 753 | break; |
| 754 | case 't': | ||
| 755 | trackdump = atoi(EARGF(usage())); | ||
| 756 | break; | ||
| 666 | }ARGEND | 757 | }ARGEND |
| 667 | 758 | ||
| 668 | fmtinstall('T', typefmt); | 759 | fmtinstall('T', typefmt); |