Unified · Split
| @@ -4,6 +4,8 @@ · 3 unmodified lines | ||
| 4 | 4 | |
| 5 | 5 | typedef struct Box Box; |
| 6 | 6 | typedef struct RunSample RunSample; |
| 7 | +typedef struct Track Track; | |
| 8 | +typedef struct SampleToChunk SampleToChunk; | |
| 7 | 9 | |
| 8 | 10 | struct Box { |
| 9 | 11 | vlong dsz; |
| @@ -88,11 +90,7 @@ struct Box { · 78 unmodified lines | ||
| 88 | 90 | |
| 89 | 91 | struct { |
| 90 | 92 | u32int entrycount; |
| 91 | − struct { | |
| 92 | − u32int firstchunk; | |
| 93 | − u32int samplesperchunk; | |
| 94 | − u32int sdt; | |
| 95 | − }*entry; | |
| 93 | + SampleToChunk *entry; | |
| 96 | 94 | }stsc; |
| 97 | 95 | |
| 98 | 96 | struct { |
| @@ -129,6 +127,25 @@ struct RunSample { · 30 unmodified lines | ||
| 129 | 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 | 149 | enum { |
| 133 | 150 | BoxUuid = 0x75756964u, |
| 134 | 151 | BoxFtyp = 0x66747970u, |
| @@ -146,6 +163,7 @@ enum { · 11 unmodified lines | ||
| 146 | 163 | BoxMinf = 0x6d696e66u, |
| 147 | 164 | BoxDinf = 0x64696e66u, |
| 148 | 165 | BoxStbl = 0x7374626cu, |
| 166 | + BoxCtts = 0x63747473u, | |
| 149 | 167 | BoxStsd = 0x73747364u, |
| 150 | 168 | BoxStts = 0x73747473u, |
| 151 | 169 | BoxStsc = 0x73747363u, |
| @@ -173,15 +191,18 @@ enum { · 21 unmodified lines | ||
| 173 | 191 | b->type == BoxMfhd || b->type == BoxTfhd || b->type == BoxTfdt || b->type == BoxTrun || \ |
| 174 | 192 | b->type == BoxStsd || b->type == BoxStts || b->type == BoxStss || b->type == BoxTkhd || \ |
| 175 | 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 | 197 | #define eBread(sz, e) if(Bread(f, d, (sz)) != (sz)){ werrstr(e); goto err; } |
| 180 | 198 | |
| 181 | 199 | static int dflag; |
| 182 | 200 | static int dind; |
| 201 | +static int trackdump = -1; | |
| 183 | 202 | static u32int defsamplesize; |
| 184 | 203 | |
| 204 | +static Track track; | |
| 205 | + | |
| 185 | 206 | static int parsebox(Biobuf *f, Box *b, int *eof); |
| 186 | 207 | |
| 187 | 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 | 397 | static int |
| 336 | 398 | parseboxdata(Biobuf *f, Box *b) |
| 337 | 399 | { |
| @@ -369,6 +431,17 @@ parseboxdata(Biobuf *f, Box *b) · 31 unmodified lines | ||
| 369 | 431 | if(inner.dstart+inner.dsz >= b->dstart+b->dsz) |
| 370 | 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 | 445 | dind--; |
| 373 | 446 | }else if(b->type == BoxMvhd){ |
| 374 | 447 | n = b->version == 0 ? 96 : 108; |
| @@ -506,7 +579,7 @@ parseboxdata(Biobuf *f, Box *b) · 131 unmodified lines | ||
| 506 | 579 | }else if(b->type == BoxStsc){ |
| 507 | 580 | eBread(4, "entry_count"); |
| 508 | 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 | 583 | for(u = 0; u < b->stsc.entrycount; u++){ |
| 511 | 584 | eBread(4, "first_chunk"); |
| 512 | 585 | b->stsc.entry[u].firstchunk = bu32(d); |
| @@ -515,6 +588,8 @@ parseboxdata(Biobuf *f, Box *b) · 2 unmodified lines | ||
| 515 | 588 | eBread(4, "sample_description_table"); |
| 516 | 589 | b->stsc.entry[u].sdt = bu32(d); |
| 517 | 590 | } |
| 591 | + track.numstc = b->stsc.entrycount; | |
| 592 | + track.stc = b->stsc.entry; | |
| 518 | 593 | printbox(b); |
| 519 | 594 | }else if(b->type == BoxStco || b->type == BoxCo64){ |
| 520 | 595 | eBread(4, "entry_count"); |
| @@ -524,6 +599,8 @@ parseboxdata(Biobuf *f, Box *b) · 3 unmodified lines | ||
| 524 | 599 | eBread(b->type == BoxStco ? 4 : 8, "chunk_offset"); |
| 525 | 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 | 604 | printbox(b); |
| 528 | 605 | }else if(b->type == BoxStsz){ |
| 529 | 606 | eBread(4, "sample_size"); |
| @@ -536,6 +613,8 @@ parseboxdata(Biobuf *f, Box *b) · 6 unmodified lines | ||
| 536 | 613 | eBread(4, "chunk_offset"); |
| 537 | 614 | b->stsz.entrysize[u] = bu32(d); |
| 538 | 615 | } |
| 616 | + track.numsamples = b->stsz.samplecount; | |
| 617 | + track.samplesize = b->stsz.entrysize; | |
| 539 | 618 | } |
| 540 | 619 | printbox(b); |
| 541 | 620 | }else if(b->type == BoxTkhd){ |
| @@ -546,6 +625,7 @@ parseboxdata(Biobuf *f, Box *b) · 4 unmodified lines | ||
| 546 | 625 | b->tkhd.modtime = bu64(d); |
| 547 | 626 | eBread(8, "track_id"); /* skipping 4 reserved as well */ |
| 548 | 627 | b->tkhd.trackid = bu32(d); |
| 628 | + track.id = b->tkhd.trackid; | |
| 549 | 629 | eBread(8, "duration"); |
| 550 | 630 | b->tkhd.duration = bu64(d); |
| 551 | 631 | }else if(b->version == 0){ |
| @@ -555,6 +635,7 @@ parseboxdata(Biobuf *f, Box *b) · 3 unmodified lines | ||
| 555 | 635 | b->tkhd.modtime = bu32(d); |
| 556 | 636 | eBread(8, "track_id"); /* skipping 4 reserved as well */ |
| 557 | 637 | b->tkhd.trackid = bu32(d); |
| 638 | + track.id = b->tkhd.trackid; | |
| 558 | 639 | eBread(4, "duration"); |
| 559 | 640 | b->tkhd.duration = bu32(d); |
| 560 | 641 | }else{ |
| @@ -651,6 +732,13 @@ err: · 90 unmodified lines | ||
| 651 | 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 | 742 | int |
| 655 | 743 | main(int argc, char **argv) |
| 656 | 744 | { |
| @@ -663,6 +751,9 @@ main(int argc, char **argv) · 6 unmodified lines | ||
| 663 | 751 | case 'd': |
| 664 | 752 | dflag = 1; |
| 665 | 753 | break; |
| 754 | + case 't': | |
| 755 | + trackdump = atoi(EARGF(usage())); | |
| 756 | + break; | |
| 666 | 757 | }ARGEND |
| 667 | 758 | |
| 668 | 759 | fmtinstall('T', typefmt); |