Changeset 263 for trunk/libmpdemux/demux_mov.c
- Timestamp:
- Nov 20, 2006, 9:45:29 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
TabularUnified trunk/libmpdemux/demux_mov.c ¶
r181 r263 31 31 #include "stheader.h" 32 32 33 #include "subreader.h" 34 35 extern subtitle* vo_sub; 36 int vo_osd_changed(int new_value); 37 #define OSDTYPE_OSD 1 38 #define OSDTYPE_SUBTITLE 2 39 #define OSDTYPE_PROGBAR 3 40 #define OSDTYPE_SPU 4 41 33 42 #include "bswap.h" 34 43 … … 53 62 54 63 #define BE_16(x) (((unsigned char *)(x))[0] << 8 | \ 55 64 ((unsigned char *)(x))[1]) 56 65 #define BE_32(x) (((unsigned char *)(x))[0] << 24 | \ 57 58 59 66 ((unsigned char *)(x))[1] << 16 | \ 67 ((unsigned char *)(x))[2] << 8 | \ 68 ((unsigned char *)(x))[3]) 60 69 61 70 #define char2short(x,y) BE_16(&(x)[(y)]) … … 164 173 if (trak->chunks_size <= 0) 165 174 { 166 167 168 169 170 171 172 175 dprintf(MSGT_DEMUX, "No chunk offset table, trying to build one!\n"); 176 177 trak->chunks_size = trak->samples_size; /* XXX: FIXME ! */ 178 trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t)*trak->chunks_size); 179 180 for (i=0; i < trak->chunks_size; i++) 181 trak->chunks[i].pos = -1; 173 182 } 174 183 #endif … … 180 189 i=trak->chunkmap_size; 181 190 while(i>0){ 182 183 184 185 186 187 191 --i; 192 for(j=trak->chunkmap[i].first;j<last;j++){ 193 trak->chunks[j].desc=trak->chunkmap[i].sdid; 194 trak->chunks[j].size=trak->chunkmap[i].spc; 195 } 196 last=trak->chunkmap[i].first; 188 197 } 189 198 … … 191 200 for (i=0; i < trak->chunks_size; i++) 192 201 { 193 194 195 196 197 198 202 /* fixup position */ 203 if (trak->chunks[i].pos == -1) 204 if (i > 0) 205 trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size; 206 else 207 trak->chunks[i].pos = 0; /* FIXME: set initial pos */ 199 208 #endif 200 209 201 // calc pts of chunks: 202 s=0; 203 for(j=0;j<trak->chunks_size;j++){ 204 trak->chunks[j].sample=s; 205 s+=trak->chunks[j].size; 210 // calc pts of chunks: 211 s=0; 212 for(j=0;j<trak->chunks_size;j++){ 213 trak->chunks[j].sample=s; 214 s+=trak->chunks[j].size; 215 } 216 i = 0; 217 for (j = 0; j < trak->durmap_size; j++) 218 i += trak->durmap[j].num; 219 if (i != s) { 220 dprintf("MOV: durmap and chunkmap sample count differ (%i vs %i)\n", i, s); 221 if (i > s) s = i; 222 } 223 224 // workaround for fixed-size video frames (dv and uncompressed) 225 if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){ 226 trak->samples_size=s; 227 trak->samples=calloc(s, sizeof(mov_sample_t)); 228 for(i=0;i<s;i++) 229 trak->samples[i].size=trak->samplesize; 230 trak->samplesize=0; 231 } 232 233 if(!trak->samples_size){ 234 // constant sampesize 235 if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){ 236 trak->duration=trak->durmap[0].dur; 237 } else dprintf("*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n"); 238 return; 239 } 240 241 if (trak->samples_size < s) { 242 dprintf("MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n", 243 s, trak->samples_size); 244 trak->samples_size = s; 245 trak->samples = realloc_struct(trak->samples, s, sizeof(mov_sample_t)); 246 } 247 248 // calc pts: 249 s=0; 250 for(j=0;j<trak->durmap_size;j++){ 251 for(i=0;i<trak->durmap[j].num;i++){ 252 trak->samples[s].pts=pts; 253 ++s; 254 pts+=trak->durmap[j].dur; 255 } 256 } 257 258 // calc sample offsets 259 s=0; 260 for(j=0;j<trak->chunks_size;j++){ 261 off_t pos=trak->chunks[j].pos; 262 for(i=0;i<trak->chunks[j].size;i++){ 263 trak->samples[s].pos=pos; 264 dprintf( "Sample %5d: pts=%8d off=0x%08X size=%d\n",s, 265 trak->samples[s].pts, 266 (int)trak->samples[s].pos, 267 trak->samples[s].size); 268 pos+=trak->samples[s].size; 269 ++s; 270 } 271 } 272 273 // precalc editlist entries 274 if(trak->editlist_size>0){ 275 int frame=0; 276 int e_pts=0; 277 for(i=0;i<trak->editlist_size;i++){ 278 mov_editlist_t* el=&trak->editlist[i]; 279 int sample=0; 280 int pts=el->pos; 281 el->start_frame=frame; 282 if(pts<0){ 283 // skip! 284 el->frames=0; continue; 285 } 286 // find start sample 287 for(;sample<trak->samples_size;sample++){ 288 if(pts<=trak->samples[sample].pts) break; 289 } 290 el->start_sample=sample; 291 el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts; 292 pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale; 293 e_pts+=el->dur; 294 // find end sample 295 for(;sample<trak->samples_size;sample++){ 296 if(pts<trak->samples[sample].pts) break; 297 } 298 el->frames=sample-el->start_sample; 299 frame+=el->frames; 300 dprintf("EL#%d: pts=%d 1st_sample=%d frames=%d (%5.3fs) pts_offs=%d\n",i, 301 el->pos,el->start_sample, el->frames, 302 (float)(el->dur)/(float)timescale, el->pts_offset); 303 } 304 } 206 305 } 207 i = 0; 208 for (j = 0; j < trak->durmap_size; j++) 209 i += trak->durmap[j].num; 210 if (i != s) { 211 dprintf( 212 "MOV: durmap and chunkmap sample count differ (%i vs %i)\n", i, s); 213 if (i > s) s = i; 306 307 #define MOV_MAX_TRACKS 256 308 #define MOV_MAX_SUBLEN 1024 309 310 typedef struct { 311 off_t moov_start; 312 off_t moov_end; 313 off_t mdat_start; 314 off_t mdat_end; 315 int track_db; 316 mov_track_t* tracks[MOV_MAX_TRACKS]; 317 int timescale; // movie timescale 318 int duration; // movie duration (in movie timescale units) 319 subtitle subs; 320 char subtext[MOV_MAX_SUBLEN + 1]; 321 int current_sub; 322 } mov_priv_t; 323 324 #define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d)) 325 326 static int mov_check_file(demuxer_t* demuxer){ 327 int flags=0; 328 int no=0; 329 mov_priv_t* priv=malloc(sizeof(mov_priv_t)); 330 331 dprintf("Checking for MOV\n"); 332 333 memset(priv,0,sizeof(mov_priv_t)); 334 priv->current_sub = -1; 335 336 while(1){ 337 int i; 338 int skipped=8; 339 off_t len=stream_read_dword(demuxer->stream); 340 unsigned int id=stream_read_dword(demuxer->stream); 341 if(stream_eof(demuxer->stream)) break; // EOF 342 if (len == 1) /* real size is 64bits - cjb */ 343 { 344 #ifndef _LARGEFILE_SOURCE 345 if (stream_read_dword(demuxer->stream) != 0) 346 dprintf( "64bit file, but you've compiled MPlayer without LARGEFILE support!\n"); 347 len = stream_read_dword(demuxer->stream); 348 #else 349 len = stream_read_qword(demuxer->stream); 350 #endif 351 skipped += 8; 352 } 353 #if 0 354 else if (len == 0) /* deleted chunk */ 355 { 356 /* XXX: CJB! is this right? - alex */ 357 goto skip_chunk; 358 } 359 #endif 360 else if(len<8) break; // invalid chunk 361 362 switch(id){ 363 case MOV_FOURCC('f','t','y','p'): { 364 unsigned int tmp; 365 // File Type Box (ftyp): 366 // char[4] major_brand (eg. 'isom') 367 // int minor_version (eg. 0x00000000) 368 // char[4] compatible_brands[] (eg. 'mp41') 369 // compatible_brands list spans to the end of box 370 #if 1 371 tmp = stream_read_dword(demuxer->stream); 372 switch(tmp) { 373 case MOV_FOURCC('i','s','o','m'): 374 dprintf("ISO: File Type Major Brand: ISO Base Media\n"); 375 break; 376 case MOV_FOURCC('m','p','4','1'): 377 dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v1\n"); 378 break; 379 case MOV_FOURCC('m','p','4','2'): 380 dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v2\n"); 381 break; 382 case MOV_FOURCC('M','4','A',' '): 383 dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Audio\n"); 384 break; 385 case MOV_FOURCC('M','4','P',' '): 386 dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n"); 387 break; 388 case MOV_FOURCC('q','t',' ',' '): 389 dprintf("ISO: File Type Major Brand: Original QuickTime\n"); 390 break; 391 case MOV_FOURCC('3','g','p','1'): 392 dprintf("ISO: File Type Major Brand: 3GPP Profile 1\n"); 393 break; 394 case MOV_FOURCC('3','g','p','2'): 395 case MOV_FOURCC('3','g','2','a'): 396 dprintf("ISO: File Type Major Brand: 3GPP Profile 2\n"); 397 break; 398 case MOV_FOURCC('3','g','p','3'): 399 dprintf("ISO: File Type Major Brand: 3GPP Profile 3\n"); 400 break; 401 case MOV_FOURCC('3','g','p','4'): 402 dprintf("ISO: File Type Major Brand: 3GPP Profile 4\n"); 403 break; 404 case MOV_FOURCC('3','g','p','5'): 405 dprintf("ISO: File Type Major Brand: 3GPP Profile 5\n"); 406 break; 407 case MOV_FOURCC('m','m','p','4'): 408 dprintf("ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n"); 409 break; 410 default: 411 tmp = be2me_32(tmp); 412 dprintf("ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp); 413 } 414 dprintf("ISO: File Type Minor Version: %d\n", 415 stream_read_dword(demuxer->stream)); 416 skipped += 8; 417 // List all compatible brands 418 for(i = 0; i < ((len-16)/4); i++) { 419 tmp = be2me_32(stream_read_dword(demuxer->stream)); 420 dprintf("ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp); 421 skipped += 4; 422 } 423 #endif 424 } break; 425 case MOV_FOURCC('m','o','o','v'): 426 // case MOV_FOURCC('c','m','o','v'): 427 dprintf("MOV: Movie header found!\n"); 428 priv->moov_start=(off_t)stream_tell(demuxer->stream); 429 priv->moov_end=(off_t)priv->moov_start+len-skipped; 430 dprintf("MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n", 431 (int64_t)priv->moov_start, (int64_t)priv->moov_end); 432 skipped+=8; 433 i = stream_read_dword(demuxer->stream)-8; 434 if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){ 435 int ref=0; 436 skipped+=i; 437 dprintf("MOV: Reference Media file!!!\n"); 438 //set demuxer type to playlist ... 439 demuxer->type=DEMUXER_TYPE_PLAYLIST; 440 while(i>0){ 441 int len=stream_read_dword(demuxer->stream)-8; 442 int fcc=stream_read_dword(demuxer->stream); 443 if(len<0) break; // EOF!? 444 i-=8; 445 // printf("i=%d len=%d\n",i,len); 446 switch(fcc){ 447 case MOV_FOURCC('r','m','d','a'): 448 continue; 449 case MOV_FOURCC('r','d','r','f'): { 450 int tmp=stream_read_dword(demuxer->stream); 451 int type=stream_read_dword_le(demuxer->stream); 452 int slen=stream_read_dword(demuxer->stream); 453 //char* s=malloc(slen+1); 454 //stream_read(demuxer->stream,s,slen); 455 456 //FIXME: also store type & data_rate ? 457 ds_read_packet(demuxer->video, 458 demuxer->stream, 459 slen, 460 0, 461 stream_tell(demuxer->stream), 462 0 // no flags 463 ); 464 flags|=4; 465 dprintf("Added reference to playlist\n"); 466 //s[slen]=0; 467 //dprintf("REF: [%.4s] %s\n",&type,s); 468 len-=12+slen;i-=12+slen; break; 469 } 470 case MOV_FOURCC('r','m','d','r'): { 471 int flags=stream_read_dword(demuxer->stream); 472 int rate=stream_read_dword(demuxer->stream); 473 dprintf(" min. data rate: %d bits/sec\n",rate); 474 len-=8; i-=8; break; 475 } 476 case MOV_FOURCC('r','m','q','u'): { 477 int q=stream_read_dword(demuxer->stream); 478 dprintf(" quality index: %d\n",q); 479 len-=4; i-=4; break; 480 } 481 } 482 i-=len;stream_skip(demuxer->stream,len); 483 } 484 } 485 flags|=1; 486 break; 487 case MOV_FOURCC('w','i','d','e'): 488 dprintf("MOV: 'WIDE' chunk found!\n"); 489 if(flags&2) break; 490 case MOV_FOURCC('m','d','a','t'): 491 dprintf("MOV: Movie DATA found!\n"); 492 priv->mdat_start=stream_tell(demuxer->stream); 493 priv->mdat_end=priv->mdat_start+len-skipped; 494 dprintf("MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n", 495 (int64_t)priv->mdat_start, (int64_t)priv->mdat_end); 496 flags|=2; 497 if(flags==3){ 498 // if we're over the headers, then we can stop parsing here! 499 demuxer->priv=priv; 500 return DEMUXER_TYPE_MOV; 501 } 502 break; 503 case MOV_FOURCC('f','r','e','e'): 504 case MOV_FOURCC('s','k','i','p'): 505 case MOV_FOURCC('j','u','n','k'): 506 dprintf("MOV: free space (len: %"PRId64")\n", (int64_t)len); 507 /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */ 508 break; 509 case MOV_FOURCC('p','n','o','t'): 510 case MOV_FOURCC('P','I','C','T'): 511 /* dunno what, but we shoudl ignore it */ 512 break; 513 default: 514 if(no==0){ free(priv); return 0;} // first chunk is bad! 515 id = be2me_32(id); 516 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 517 } 518 skip_chunk: 519 if(!stream_skip(demuxer->stream,len-skipped)) break; 520 ++no; 521 } 522 523 if(flags==3){ 524 demuxer->priv=priv; 525 return DEMUXER_TYPE_MOV; 526 } 527 free(priv); 528 529 if ((flags==5) || (flags==7)) // reference & header sent 530 return DEMUXER_TYPE_PLAYLIST; 531 532 if(flags==1) 533 dprintf("MOV: missing data (mdat) chunk! Maybe broken file...\n"); 534 else if(flags==2) 535 dprintf("MOV: missing header (moov/cmov) chunk! Maybe broken file...\n"); 536 537 return 0; 214 538 } 215 539 216 // workaround for fixed-size video frames (dv and uncompressed) 217 if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){ 218 trak->samples_size=s; 219 trak->samples=calloc(s, sizeof(mov_sample_t)); 220 for(i=0;i<s;i++) 221 trak->samples[i].size=trak->samplesize; 222 trak->samplesize=0; 540 static void demux_close_mov(demuxer_t *demuxer) { 541 mov_priv_t* priv = demuxer->priv; 542 int i; 543 if (!priv) 544 return; 545 for (i = 0; i < MOV_MAX_TRACKS; i++) { 546 mov_track_t *track = priv->tracks[i]; 547 if (track) { 548 free(track->tkdata); 549 free(track->stdata); 550 free(track->stream_header); 551 free(track->samples); 552 free(track->chunks); 553 free(track->chunkmap); 554 free(track->durmap); 555 free(track->keyframes); 556 free(track->editlist); 557 free(track->desc); 558 free(track); 559 } 560 } 561 free(priv); 223 562 } 224 563 225 if(!trak->samples_size){ 226 // constant sampesize 227 if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){ 228 trak->duration=trak->durmap[0].dur; 229 } else dprintf( "*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n"); 230 return; 564 unsigned int store_ughvlc(unsigned char *s, unsigned int v){ 565 unsigned int n = 0; 566 567 while(v >= 0xff) { 568 *s++ = 0xff; 569 v -= 0xff; 570 n++; 571 } 572 *s = v; 573 n++; 574 575 return n; 231 576 } 232 577 233 if (trak->samples_size < s) { 234 dprintf( 235 "MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n", 236 s, trak->samples_size); 237 trak->samples_size = s; 238 trak->samples = realloc_struct(trak->samples, s, sizeof(mov_sample_t)); 578 static void init_vobsub(sh_sub_t *sh, mov_track_t *trak) { 579 int i; 580 uint8_t *pal = trak->stdata; 581 sh->type = 'v'; 582 if (trak->stdata_len < 106) 583 return; 584 sh->has_palette = 1; 585 pal += 42; 586 for (i = 0; i < 16; i++) { 587 sh->palette[i] = BE_32(pal); 588 pal += 4; 589 } 239 590 } 240 241 // calc pts: 242 s=0; 243 for(j=0;j<trak->durmap_size;j++){ 244 for(i=0;i<trak->durmap[j].num;i++){ 245 trak->samples[s].pts=pts; 246 ++s; 247 pts+=trak->durmap[j].dur; 248 } 249 } 250 251 // calc sample offsets 252 s=0; 253 for(j=0;j<trak->chunks_size;j++){ 254 off_t pos=trak->chunks[j].pos; 255 for(i=0;i<trak->chunks[j].size;i++){ 256 trak->samples[s].pos=pos; 257 dprintf( "Sample %5d: pts=%8d off=0x%08X size=%d\n",s, 258 trak->samples[s].pts, 259 (int)trak->samples[s].pos, 260 trak->samples[s].size); 261 pos+=trak->samples[s].size; 262 ++s; 263 } 264 } 265 266 // precalc editlist entries 267 if(trak->editlist_size>0){ 268 int frame=0; 269 int e_pts=0; 270 for(i=0;i<trak->editlist_size;i++){ 271 mov_editlist_t* el=&trak->editlist[i]; 272 int sample=0; 273 int pts=el->pos; 274 el->start_frame=frame; 275 if(pts<0){ 276 // skip! 277 el->frames=0; continue; 278 } 279 // find start sample 280 for(;sample<trak->samples_size;sample++){ 281 if(pts<=trak->samples[sample].pts) break; 282 } 283 el->start_sample=sample; 284 el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts; 285 pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale; 286 e_pts+=el->dur; 287 // find end sample 288 for(;sample<trak->samples_size;sample++){ 289 if(pts<trak->samples[sample].pts) break; 290 } 291 el->frames=sample-el->start_sample; 292 frame+=el->frames; 293 dprintf("EL#%d: pts=%d 1st_sample=%d frames=%d (%5.3fs) pts_offs=%d\n",i, 294 el->pos,el->start_sample, el->frames, 295 (float)(el->dur)/(float)timescale, el->pts_offset); 296 } 297 } 298 299 } 300 301 #define MOV_MAX_TRACKS 256 302 303 typedef struct { 304 off_t moov_start; 305 off_t moov_end; 306 off_t mdat_start; 307 off_t mdat_end; 308 int track_db; 309 mov_track_t* tracks[MOV_MAX_TRACKS]; 310 int timescale; // movie timescale 311 int duration; // movie duration (in movie timescale units) 312 } mov_priv_t; 313 314 #define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d)) 315 316 static int mov_check_file(demuxer_t* demuxer){ 317 int flags=0; 318 int no=0; 319 mov_priv_t* priv=malloc(sizeof(mov_priv_t)); 320 321 dprintf("Checking for MOV\n"); 322 323 memset(priv,0,sizeof(mov_priv_t)); 324 325 while(1){ 326 int i; 327 int skipped=8; 328 off_t len=stream_read_dword(demuxer->stream); 329 unsigned int id=stream_read_dword(demuxer->stream); 330 if(stream_eof(demuxer->stream)) break; // EOF 331 if (len == 1) /* real size is 64bits - cjb */ 332 { 333 #ifndef _LARGEFILE_SOURCE 334 if (stream_read_dword(demuxer->stream) != 0) 335 dprintf( "64bit file, but you've compiled MPlayer without LARGEFILE support!\n"); 336 len = stream_read_dword(demuxer->stream); 337 #else 338 len = stream_read_qword(demuxer->stream); 591 592 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, 593 off_t pos, off_t len, mov_track_t* trak); 594 595 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ 596 mov_priv_t* priv=demuxer->priv; 597 // printf("lschunks (level=%d,endpos=%x)\n", level, endpos); 598 while(1){ 599 off_t pos; 600 off_t len; 601 unsigned int id; 602 // 603 pos=stream_tell(demuxer->stream); 604 dprintf("MOV: stream_tell==%lli\n",pos); 605 if(pos>=endpos) return; // END 606 len=stream_read_dword(demuxer->stream); 607 // printf("len==%d\n",len); 608 if(len<8) return; // error 609 len-=8; 610 id=stream_read_dword(demuxer->stream); 611 // 612 dprintf("lschunks %.4s %d\n",(char *)&id,(int)len); 613 // 614 if(trak){ 615 if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0) 616 return; 617 } else { /* not in track */ 618 switch(id) { 619 case MOV_FOURCC('m','v','h','d'): { 620 int version = stream_read_char(demuxer->stream); 621 stream_skip(demuxer->stream, (version == 1) ? 19 : 11); 622 priv->timescale=stream_read_dword(demuxer->stream); 623 if (version == 1) 624 priv->duration=stream_read_qword(demuxer->stream); 625 else 626 priv->duration=stream_read_dword(demuxer->stream); 627 dprintf("MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len, 628 (int)priv->timescale,(int)priv->duration); 629 break; 630 } 631 case MOV_FOURCC('t','r','a','k'): { 632 // if(trak) printf("MOV: Warning! trak in trak?\n"); 633 if(priv->track_db>=MOV_MAX_TRACKS){ 634 dprintf("MOV: too may tracks\n"); 635 return; 636 } 637 if(!priv->track_db) dprintf( "--------------\n"); 638 trak=malloc(sizeof(mov_track_t)); 639 memset(trak,0,sizeof(mov_track_t)); 640 dprintf("MOV: Track #%d:\n",priv->track_db); 641 trak->id=priv->track_db; 642 priv->tracks[priv->track_db]=trak; 643 lschunks(demuxer,level+1,pos+len,trak); 644 mov_build_index(trak,priv->timescale); 645 switch(trak->type){ 646 case MOV_TRAK_AUDIO: { 647 #if 0 648 struct { 649 int16_t version; // 0 or 1 (version 1 is qt3.0+) 650 int16_t revision; // 0 651 int32_t vendor_id; // 0 652 int16_t channels; // 1 or 2 (Mono/Stereo) 653 int16_t samplesize; // 8 or 16 (8Bit/16Bit) 654 int16_t compression_id; // if version 0 then 0 655 // if version 1 and vbr then -2 else 0 656 int16_t packet_size; // 0 657 uint16_t sample_rate; // samplerate (Hz) 658 // qt3.0+ (version == 1) 659 uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet 660 // if 0 below three values are also 0 661 uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel 662 uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels 663 // (channels * bytes_per_packet) 664 uint32_t bytes_per_sample; // 0 or size of uncompressed sample 665 // if samples_per_packet and bytes_per_packet are constant (CBR) 666 // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR) 667 // --- 668 // optional additional atom-based fields 669 // ([int32_t size,int32_t type,some data ],repeat) 670 } my_stdata; 339 671 #endif 340 skipped += 8; 341 } 342 #if 0 343 else if (len == 0) /* deleted chunk */ 344 { 345 /* XXX: CJB! is this right? - alex */ 346 goto skip_chunk; 347 } 348 #endif 349 else if(len<8) break; // invalid chunk 350 351 switch(id){ 352 case MOV_FOURCC('f','t','y','p'): { 353 unsigned int tmp; 354 // File Type Box (ftyp): 355 // char[4] major_brand (eg. 'isom') 356 // int minor_version (eg. 0x00000000) 357 // char[4] compatible_brands[] (eg. 'mp41') 358 // compatible_brands list spans to the end of box 359 #if 1 360 tmp = stream_read_dword(demuxer->stream); 361 switch(tmp) { 362 case MOV_FOURCC('i','s','o','m'): 363 dprintf("ISO: File Type Major Brand: ISO Base Media\n"); 364 break; 365 case MOV_FOURCC('m','p','4','1'): 366 dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v1\n"); 367 break; 368 case MOV_FOURCC('m','p','4','2'): 369 dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v2\n"); 370 break; 371 case MOV_FOURCC('M','4','A',' '): 372 dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Audio\n"); 373 break; 374 case MOV_FOURCC('M','4','P',' '): 375 dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n"); 376 break; 377 case MOV_FOURCC('q','t',' ',' '): 378 dprintf("ISO: File Type Major Brand: Original QuickTime\n"); 379 break; 380 case MOV_FOURCC('3','g','p','1'): 381 dprintf("ISO: File Type Major Brand: 3GPP Profile 1\n"); 382 break; 383 case MOV_FOURCC('3','g','p','2'): 384 case MOV_FOURCC('3','g','2','a'): 385 dprintf("ISO: File Type Major Brand: 3GPP Profile 2\n"); 386 break; 387 case MOV_FOURCC('3','g','p','3'): 388 dprintf("ISO: File Type Major Brand: 3GPP Profile 3\n"); 389 break; 390 case MOV_FOURCC('3','g','p','4'): 391 dprintf("ISO: File Type Major Brand: 3GPP Profile 4\n"); 392 break; 393 case MOV_FOURCC('3','g','p','5'): 394 dprintf("ISO: File Type Major Brand: 3GPP Profile 5\n"); 395 break; 396 case MOV_FOURCC('m','m','p','4'): 397 dprintf("ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n"); 398 break; 399 default: 400 tmp = be2me_32(tmp); 401 dprintf("ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp); 402 } 403 dprintf("ISO: File Type Minor Version: %d\n", 404 stream_read_dword(demuxer->stream)); 405 skipped += 8; 406 // List all compatible brands 407 for(i = 0; i < ((len-16)/4); i++) { 408 tmp = be2me_32(stream_read_dword(demuxer->stream)); 409 dprintf("ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp); 410 skipped += 4; 411 } 412 #endif 413 } break; 414 case MOV_FOURCC('m','o','o','v'): 415 // case MOV_FOURCC('c','m','o','v'): 416 dprintf("MOV: Movie header found!\n"); 417 priv->moov_start=(off_t)stream_tell(demuxer->stream); 418 priv->moov_end=(off_t)priv->moov_start+len-skipped; 419 dprintf("MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n", 420 (int64_t)priv->moov_start, (int64_t)priv->moov_end); 421 skipped+=8; 422 i = stream_read_dword(demuxer->stream)-8; 423 if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){ 424 int ref=0; 425 skipped+=i; 426 dprintf("MOV: Reference Media file!!!\n"); 427 //set demuxer type to playlist ... 428 demuxer->type=DEMUXER_TYPE_PLAYLIST; 429 while(i>0){ 430 int len=stream_read_dword(demuxer->stream)-8; 431 int fcc=stream_read_dword(demuxer->stream); 432 if(len<0) break; // EOF!? 433 i-=8; 434 // printf("i=%d len=%d\n",i,len); 435 switch(fcc){ 436 case MOV_FOURCC('r','m','d','a'): 437 continue; 438 case MOV_FOURCC('r','d','r','f'): { 439 int tmp=stream_read_dword(demuxer->stream); 440 int type=stream_read_dword_le(demuxer->stream); 441 int slen=stream_read_dword(demuxer->stream); 442 //char* s=malloc(slen+1); 443 //stream_read(demuxer->stream,s,slen); 444 445 //FIXME: also store type & data_rate ? 446 ds_read_packet(demuxer->video, 447 demuxer->stream, 448 slen, 449 0, 450 stream_tell(demuxer->stream), 451 0 // no flags 452 ); 453 flags|=4; 454 dprintf("Added reference to playlist\n"); 455 //s[slen]=0; 456 //dprintf("REF: [%.4s] %s\n",&type,s); 457 len-=12+slen;i-=12+slen; break; 458 } 459 case MOV_FOURCC('r','m','d','r'): { 460 int flags=stream_read_dword(demuxer->stream); 461 int rate=stream_read_dword(demuxer->stream); 462 dprintf(" min. data rate: %d bits/sec\n",rate); 463 len-=8; i-=8; break; 464 } 465 case MOV_FOURCC('r','m','q','u'): { 466 int q=stream_read_dword(demuxer->stream); 467 dprintf(" quality index: %d\n",q); 468 len-=4; i-=4; break; 469 } 470 } 471 i-=len;stream_skip(demuxer->stream,len); 472 } 473 } 474 flags|=1; 475 break; 476 case MOV_FOURCC('w','i','d','e'): 477 dprintf("MOV: 'WIDE' chunk found!\n"); 478 if(flags&2) break; 479 case MOV_FOURCC('m','d','a','t'): 480 dprintf("MOV: Movie DATA found!\n"); 481 priv->mdat_start=stream_tell(demuxer->stream); 482 priv->mdat_end=priv->mdat_start+len-skipped; 483 dprintf("MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n", 484 (int64_t)priv->mdat_start, (int64_t)priv->mdat_end); 485 flags|=2; 486 if(flags==3){ 487 // if we're over the headers, then we can stop parsing here! 488 demuxer->priv=priv; 489 return DEMUXER_TYPE_MOV; 490 } 491 break; 492 case MOV_FOURCC('f','r','e','e'): 493 case MOV_FOURCC('s','k','i','p'): 494 case MOV_FOURCC('j','u','n','k'): 495 dprintf("MOV: free space (len: %"PRId64")\n", (int64_t)len); 496 /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */ 497 break; 498 case MOV_FOURCC('p','n','o','t'): 499 case MOV_FOURCC('P','I','C','T'): 500 /* dunno what, but we shoudl ignore it */ 501 break; 502 default: 503 if(no==0){ free(priv); return 0;} // first chunk is bad! 504 id = be2me_32(id); 505 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 506 } 507 skip_chunk: 508 if(!stream_skip(demuxer->stream,len-skipped)) break; 509 ++no; 510 } 511 512 if(flags==3){ 513 demuxer->priv=priv; 514 return DEMUXER_TYPE_MOV; 515 } 516 free(priv); 517 518 if ((flags==5) || (flags==7)) // reference & header sent 519 return DEMUXER_TYPE_PLAYLIST; 520 521 if(flags==1) 522 dprintf("MOV: missing data (mdat) chunk! Maybe broken file...\n"); 523 else if(flags==2) 524 dprintf("MOV: missing header (moov/cmov) chunk! Maybe broken file...\n"); 525 526 return 0; 527 } 528 529 static void demux_close_mov(demuxer_t *demuxer) { 530 mov_priv_t* priv = demuxer->priv; 531 int i; 532 if (!priv) 533 return; 534 for (i = 0; i < MOV_MAX_TRACKS; i++) { 535 mov_track_t *track = priv->tracks[i]; 536 if (track) { 537 free(track->tkdata); 538 free(track->stdata); 539 free(track->stream_header); 540 free(track->samples); 541 free(track->chunks); 542 free(track->chunkmap); 543 free(track->durmap); 544 free(track->keyframes); 545 free(track->editlist); 546 free(track->desc); 547 free(track); 548 } 549 } 550 free(priv); 551 } 552 553 unsigned int store_ughvlc(unsigned char *s, unsigned int v){ 554 unsigned int n = 0; 555 556 while(v >= 0xff) { 557 *s++ = 0xff; 558 v -= 0xff; 559 n++; 560 } 561 *s = v; 562 n++; 563 564 return n; 565 } 566 567 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, 568 off_t pos, off_t len, mov_track_t* trak); 569 570 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ 571 mov_priv_t* priv=demuxer->priv; 572 // printf("lschunks (level=%d,endpos=%x)\n", level, endpos); 573 while(1){ 574 off_t pos; 575 off_t len; 576 unsigned int id; 577 // 578 pos=stream_tell(demuxer->stream); 579 dprintf("MOV: stream_tell==%lli\n",pos); 580 if(pos>=endpos) return; // END 581 len=stream_read_dword(demuxer->stream); 582 // printf("len==%d\n",len); 583 if(len<8) return; // error 584 len-=8; 585 id=stream_read_dword(demuxer->stream); 586 // 587 dprintf("lschunks %.4s %d\n",(char *)&id,(int)len); 588 // 589 if(trak){ 590 if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0) 591 return; 592 } else { /* not in track */ 593 switch(id) { 594 case MOV_FOURCC('m','v','h','d'): { 595 int version = stream_read_char(demuxer->stream); 596 stream_skip(demuxer->stream, (version == 1) ? 19 : 11); 597 priv->timescale=stream_read_dword(demuxer->stream); 598 if (version == 1) 599 priv->duration=stream_read_qword(demuxer->stream); 600 else 601 priv->duration=stream_read_dword(demuxer->stream); 602 dprintf("MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len, 603 (int)priv->timescale,(int)priv->duration); 604 break; 605 } 606 case MOV_FOURCC('t','r','a','k'): { 607 // if(trak) printf("MOV: Warning! trak in trak?\n"); 608 if(priv->track_db>=MOV_MAX_TRACKS){ 609 dprintf("MOV: too may tracks\n"); 610 return; 611 } 612 if(!priv->track_db) dprintf( "--------------\n"); 613 trak=malloc(sizeof(mov_track_t)); 614 memset(trak,0,sizeof(mov_track_t)); 615 dprintf("MOV: Track #%d:\n",priv->track_db); 616 trak->id=priv->track_db; 617 priv->tracks[priv->track_db]=trak; 618 lschunks(demuxer,level+1,pos+len,trak); 619 mov_build_index(trak,priv->timescale); 620 switch(trak->type){ 621 case MOV_TRAK_AUDIO: { 622 #if 0 623 struct { 624 int16_t version; // 0 or 1 (version 1 is qt3.0+) 625 int16_t revision; // 0 626 int32_t vendor_id; // 0 627 int16_t channels; // 1 or 2 (Mono/Stereo) 628 int16_t samplesize; // 8 or 16 (8Bit/16Bit) 629 int16_t compression_id; // if version 0 then 0 630 // if version 1 and vbr then -2 else 0 631 int16_t packet_size; // 0 632 uint16_t sample_rate; // samplerate (Hz) 633 // qt3.0+ (version == 1) 634 uint32_t samples_per_packet; // 0 or num uncompressed samples in a packet 635 // if 0 below three values are also 0 636 uint32_t bytes_per_packet; // 0 or num compressed bytes for one channel 637 uint32_t bytes_per_frame; // 0 or num compressed bytes for all channels 638 // (channels * bytes_per_packet) 639 uint32_t bytes_per_sample; // 0 or size of uncompressed sample 640 // if samples_per_packet and bytes_per_packet are constant (CBR) 641 // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR) 642 // --- 643 // optional additional atom-based fields 644 // ([int32_t size,int32_t type,some data ],repeat) 645 } my_stdata; 646 #endif 647 int version, adjust; 648 int is_vorbis = 0; 649 sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); 650 sh->format=trak->fourcc; 651 652 // crude audio delay from editlist0 hack ::atm 653 if(trak->editlist_size>=1) { 654 if(trak->editlist[0].pos == -1) { 655 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 656 dprintf("MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay); 672 int version, adjust; 673 int is_vorbis = 0; 674 sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db); 675 sh->format=trak->fourcc; 676 677 // crude audio delay from editlist0 hack ::atm 678 if(trak->editlist_size>=1) { 679 if(trak->editlist[0].pos == -1) { 680 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 681 dprintf("MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay); 682 } 657 683 } 658 } 659 660 switch( sh->format ) { 661 case 0x726D6173: /* samr */ 662 /* amr narrowband */ 663 trak->samplebytes=sh->samplesize=1; 664 trak->nchannels=sh->channels=1; 665 sh->samplerate=8000; 666 break; 667 668 case 0x62776173: /* sawb */ 669 /* amr wideband */ 670 trak->samplebytes=sh->samplesize=1; 671 trak->nchannels=sh->channels=1; 672 sh->samplerate=16000; 673 break; 674 675 default: 676 677 // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit 678 // XXX: 32bit fixed point numbers (intfp) are only 2 Byte! 679 // short values are usually one byte leftpadded by zero 680 // int values are usually two byte leftpadded by zero 681 // stdata[]: 682 // 8 short version 683 // 10 short revision 684 // 12 int vendor_id 685 // 16 short channels 686 // 18 short samplesize 687 // 20 short compression_id 688 // 22 short packet_size (==0) 689 // 24 intfp sample_rate 690 // (26 short) unknown (==0) 691 // ---- qt3.0+ (version>=1) 692 // 28 int samples_per_packet 693 // 32 int bytes_per_packet 694 // 36 int bytes_per_frame 695 // 40 int bytes_per_sample 696 // there may be additional atoms following at 28 (version 0) 697 // or 44 (version 1), eg. esds atom of .MP4 files 698 // esds atom: 699 // 28 int atom size (bytes of int size, int type and data) 700 // 32 char[4] atom type (fourc charater code -> esds) 701 // 36 char[] atom data (len=size-8) 702 703 // TODO: fix parsing for files using version 2. 704 version=char2short(trak->stdata,8); 705 if (version > 1) 706 dprintf( "MOV: version %d sound atom may not parse correctly!\n", version); 707 trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; 708 709 /* I can't find documentation, but so far this is the case. -Corey */ 710 switch (char2short(trak->stdata,16)) { 711 case 1: 712 trak->nchannels = 1; break; 713 case 2: 714 trak->nchannels = 2; break; 715 case 3: 716 trak->nchannels = 6; break; 684 685 switch( sh->format ) { 686 case 0x726D6173: /* samr */ 687 /* amr narrowband */ 688 trak->samplebytes=sh->samplesize=1; 689 trak->nchannels=sh->channels=1; 690 sh->samplerate=8000; 691 break; 692 693 case 0x62776173: /* sawb */ 694 /* amr wideband */ 695 trak->samplebytes=sh->samplesize=1; 696 trak->nchannels=sh->channels=1; 697 sh->samplerate=16000; 698 break; 699 717 700 default: 718 dprintf( 719 "MOV: unable to determine audio channels, assuming 2 (got %d)\n", 720 char2short(trak->stdata,16)); 721 trak->nchannels = 2; 722 } 723 sh->channels = trak->nchannels; 724 725 /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n", 726 trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur, 727 trak->durmap[0].num, trak->timescale/trak->durmap[0].dur, 728 char2short(trak->stdata,24)/trak->durmap[0].dur);*/ 729 sh->samplerate=char2short(trak->stdata,24); 730 if((sh->samplerate < 7000) && trak->durmap) { 731 switch(char2short(trak->stdata,24)/trak->durmap[0].dur) { 732 // TODO: add more cases. 733 case 31: 734 sh->samplerate = 32000; break; 735 case 43: 736 sh->samplerate = 44100; break; 737 case 47: 738 sh->samplerate = 48000; break; 701 702 // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit 703 // XXX: 32bit fixed point numbers (intfp) are only 2 Byte! 704 // short values are usually one byte leftpadded by zero 705 // int values are usually two byte leftpadded by zero 706 // stdata[]: 707 // 8 short version 708 // 10 short revision 709 // 12 int vendor_id 710 // 16 short channels 711 // 18 short samplesize 712 // 20 short compression_id 713 // 22 short packet_size (==0) 714 // 24 intfp sample_rate 715 // (26 short) unknown (==0) 716 // ---- qt3.0+ (version>=1) 717 // 28 int samples_per_packet 718 // 32 int bytes_per_packet 719 // 36 int bytes_per_frame 720 // 40 int bytes_per_sample 721 // there may be additional atoms following at 28 (version 0) 722 // or 44 (version 1), eg. esds atom of .MP4 files 723 // esds atom: 724 // 28 int atom size (bytes of int size, int type and data) 725 // 32 char[4] atom type (fourc charater code -> esds) 726 // 36 char[] atom data (len=size-8) 727 728 // TODO: fix parsing for files using version 2. 729 version=char2short(trak->stdata,8); 730 if (version > 1) 731 dprintf( "MOV: version %d sound atom may not parse correctly!\n", version); 732 trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8; 733 734 /* I can't find documentation, but so far this is the case. -Corey */ 735 switch (char2short(trak->stdata,16)) { 736 case 1: 737 trak->nchannels = 1; break; 738 case 2: 739 trak->nchannels = 2; break; 740 case 3: 741 trak->nchannels = 6; break; 739 742 default: 740 743 dprintf( 741 "MOV: unable to determine audio samplerate, " 742 "assuming 44.1kHz (got %d)\n", 743 char2short(trak->stdata,24)/trak->durmap[0].dur); 744 sh->samplerate = 44100; 744 "MOV: unable to determine audio channels, assuming 2 (got %d)\n", 745 char2short(trak->stdata,16)); 746 trak->nchannels = 2; 747 } 748 sh->channels = trak->nchannels; 749 750 /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n", 751 trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur, 752 trak->durmap[0].num, trak->timescale/trak->durmap[0].dur, 753 char2short(trak->stdata,24)/trak->durmap[0].dur);*/ 754 sh->samplerate=char2short(trak->stdata,24); 755 if((sh->samplerate < 7000) && trak->durmap) { 756 switch(char2short(trak->stdata,24)/trak->durmap[0].dur) { 757 // TODO: add more cases. 758 case 31: 759 sh->samplerate = 32000; break; 760 case 43: 761 sh->samplerate = 44100; break; 762 case 47: 763 sh->samplerate = 48000; break; 764 default: 765 dprintf( 766 "MOV: unable to determine audio samplerate, " 767 "assuming 44.1kHz (got %d)\n", 768 char2short(trak->stdata,24)/trak->durmap[0].dur); 769 sh->samplerate = 44100; 770 } 745 771 } 746 772 } 747 } 748 dprintf( "Audio bits: %d chans: %d rate: %d\n", 749 sh->samplesize*8,sh->channels,sh->samplerate); 750 751 if(trak->stdata_len >= 44 && trak->stdata[9]>=1){ 752 dprintf("Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n", 753 char2int(trak->stdata,28), 754 char2int(trak->stdata,32), 755 char2int(trak->stdata,36), 756 char2int(trak->stdata,40)); 757 if(trak->stdata_len>=44+8){ 758 int len=char2int(trak->stdata,44); 759 int fcc=char2int(trak->stdata,48); 760 // we have extra audio headers!!! 761 dprintf("Audio extra header: len=%d fcc=0x%X\n",len,fcc); 762 if((len >= 4) && 763 (char2int(trak->stdata,52) >= 12) && 764 (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) { 765 switch(char2int(trak->stdata,52+8)) { 766 case MOV_FOURCC('a','l','a','c'): 767 if (len >= 36 + char2int(trak->stdata,52)) { 768 sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); 769 dprintf( "MOV: Found alac atom (%d)!\n", sh->codecdata_len); 770 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 771 memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); 773 dprintf( "Audio bits: %d chans: %d rate: %d\n", 774 sh->samplesize*8,sh->channels,sh->samplerate); 775 776 if(trak->stdata_len >= 44 && trak->stdata[9]>=1){ 777 dprintf("Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d \n", 778 char2int(trak->stdata,28), 779 char2int(trak->stdata,32), 780 char2int(trak->stdata,36), 781 char2int(trak->stdata,40)); 782 if(trak->stdata_len>=44+8){ 783 int len=char2int(trak->stdata,44); 784 int fcc=char2int(trak->stdata,48); 785 // we have extra audio headers!!! 786 dprintf("Audio extra header: len=%d fcc=0x%X\n",len,fcc); 787 if((len >= 4) && 788 (char2int(trak->stdata,52) >= 12) && 789 (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) { 790 switch(char2int(trak->stdata,52+8)) { 791 case MOV_FOURCC('a','l','a','c'): 792 if (len >= 36 + char2int(trak->stdata,52)) { 793 sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52)); 794 dprintf( "MOV: Found alac atom (%d)!\n", sh->codecdata_len); 795 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 796 memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len); 797 } 798 break; 799 case MOV_FOURCC('i','n','2','4'): 800 case MOV_FOURCC('i','n','3','2'): 801 case MOV_FOURCC('f','l','3','2'): 802 case MOV_FOURCC('f','l','6','4'): 803 if ((len >= 22) && 804 (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) && 805 (char2short(trak->stdata,52+20))) { 806 sh->format=char2int(trak->stdata,52+8); 807 dprintf( "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format); 808 } 809 break; 810 default: 811 if (len > 8 && len + 44 <= trak->stdata_len) { 812 sh->codecdata_len = len-8; 813 sh->codecdata = trak->stdata+44+8; 814 } 772 815 } 773 break; 774 case MOV_FOURCC('i','n','2','4'): 775 case MOV_FOURCC('i','n','3','2'): 776 case MOV_FOURCC('f','l','3','2'): 777 case MOV_FOURCC('f','l','6','4'): 778 if ((len >= 22) && 779 (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) && 780 (char2short(trak->stdata,52+20))) { 781 sh->format=char2int(trak->stdata,52+8); 782 dprintf( "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format); 783 } 784 break; 785 default: 816 } else { 786 817 if (len > 8 && len + 44 <= trak->stdata_len) { 787 818 sh->codecdata_len = len-8; … … 789 820 } 790 821 } 791 } else { 792 if (len > 8 && len + 44 <= trak->stdata_len) { 793 sh->codecdata_len = len-8; 794 sh->codecdata = trak->stdata+44+8; 822 } 823 } 824 825 switch (version) { 826 case 0: 827 adjust = 0; break; 828 case 1: 829 adjust = 48; break; 830 case 2: 831 adjust = 68; break; 832 default: 833 dprintf( "MOV: unknown sound atom version (%d); may not work!\n", version); 834 adjust = 68; 835 } 836 if (trak->stdata_len >= 36 + adjust) { 837 int atom_len = char2int(trak->stdata,28+adjust); 838 switch(char2int(trak->stdata,32+adjust)) { // atom type 839 case MOV_FOURCC('e','s','d','s'): { 840 dprintf( "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); 841 if(atom_len > 8) { 842 esds_t esds; 843 if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { 844 /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html), 845 so perform some extra checks to be sure that this is really vorbis audio */ 846 if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8) 847 { 848 //vorbis audio 849 unsigned char *buf[3]; 850 unsigned short sizes[3]; 851 int offset, len, k; 852 unsigned char *ptr = esds.decoderConfig; 853 854 if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout 855 856 offset = len = 0; 857 for(k = 0; k < 3; k++) 858 { 859 sizes[k] = (ptr[offset]<<8) | ptr[offset+1]; 860 len += sizes[k]; 861 offset += 2; 862 if(offset + sizes[k] > esds.decoderConfigLen) 863 { 864 dprintf("MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen); 865 goto quit_vorbis_block; 866 } 867 buf[k] = malloc(sizes[k]); 868 if(!buf[k]) goto quit_vorbis_block; 869 memcpy(buf[k], &ptr[offset], sizes[k]); 870 offset += sizes[k]; 871 } 872 873 sh->codecdata_len = len + len/255 + 64; 874 sh->codecdata = malloc(sh->codecdata_len); 875 ptr = sh->codecdata; 876 877 ptr[0] = 2; 878 offset = 1; 879 offset += store_ughvlc(&ptr[offset], sizes[0]); 880 offset += store_ughvlc(&ptr[offset], sizes[1]); 881 for(k = 0; k < 3; k++) 882 { 883 memcpy(&ptr[offset], buf[k], sizes[k]); 884 offset += sizes[k]; 885 } 886 887 sh->codecdata_len = offset; 888 sh->codecdata = realloc(sh->codecdata, offset); 889 dprintf("demux_mov, vorbis extradata size: %d\n", offset); 890 is_vorbis = 1; 891 quit_vorbis_block: 892 sh->format = mmioFOURCC('v', 'r', 'b', 's'); 893 } 894 sh->i_bps = esds.avgBitrate/8; 895 896 // printf("######## audio format = %d ########\n",esds.objectTypeId); 897 if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) 898 sh->format=0x55; // .mp3 899 if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2 900 sh->format=mmioFOURCC('Q', 'c', 'l', 'p'); 901 trak->nchannels=sh->channels=1; 902 trak->samplebytes=sh->samplesize=1; 903 } 904 905 // dump away the codec specific configuration for the AAC decoder 906 if(esds.decoderConfigLen){ 907 if( (esds.decoderConfig[0]>>3) == 29 ) 908 sh->format = 0x1d61346d; // request multi-channel mp3 decoder 909 if(!is_vorbis) 910 { 911 sh->codecdata_len = esds.decoderConfigLen; 912 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 913 memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); 914 } 915 } 916 } 917 mp4_free_esds(&esds); // freeup esds mem 918 #if 0 919 { FILE* f=fopen("esds.dat","wb"); 920 fwrite(&trak->stdata[36],atom_len-8,1,f); 921 fclose(f); } 922 #endif 923 } 924 } break; 925 case MOV_FOURCC('a','l','a','c'): { 926 dprintf( "MOV: Found alac atom (%d)!\n", atom_len); 927 if(atom_len > 8) { 928 // copy all the atom (not only payload) for lavc alac decoder 929 sh->codecdata_len = atom_len; 930 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 931 memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); 932 } 933 } break; 934 case MOV_FOURCC('d','a','m','r'): 935 dprintf( "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); 936 if (atom_len>14) { 937 dprintf( "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]); 938 dprintf( "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]); 939 dprintf( "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]); 940 } 941 break; 942 default: 943 dprintf( "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", 944 trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], 945 atom_len); 946 } 947 } 948 dprintf( "Fourcc: %.4s\n",(char *)&trak->fourcc); 949 #if 0 950 { FILE* f=fopen("stdata.dat","wb"); 951 fwrite(trak->stdata,trak->stdata_len,1,f); 952 fclose(f); } 953 { FILE* f=fopen("tkdata.dat","wb"); 954 fwrite(trak->tkdata,trak->tkdata_len,1,f); 955 fclose(f); } 956 #endif 957 // Emulate WAVEFORMATEX struct: 958 sh->wf=malloc(sizeof(WAVEFORMATEX) + (is_vorbis ? sh->codecdata_len : 0)); 959 memset(sh->wf,0,sizeof(WAVEFORMATEX)); 960 sh->wf->nChannels=sh->channels; 961 sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; 962 // sh->wf->nSamplesPerSec=trak->timescale; 963 sh->wf->nSamplesPerSec=sh->samplerate; 964 if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ 965 //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 966 sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* 967 char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) 968 /char2int(trak->stdata,28); 969 sh->wf->nBlockAlign=char2int(trak->stdata,36); 970 } else { 971 sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; 972 // workaround for ms11 ima4 973 if (sh->format == 0x1100736d && trak->stdata_len >= 36) 974 sh->wf->nBlockAlign=char2int(trak->stdata,36); 975 } 976 if(is_vorbis && sh->codecdata_len) 977 { 978 memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len); 979 sh->wf->cbSize = sh->codecdata_len; 980 } 981 // Selection: 982 // if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ 983 // // (auto)selected audio track: 984 // demuxer->audio->id=priv->track_db; 985 // demuxer->audio->sh=sh; sh->ds=demuxer->audio; 986 // } 987 break; 988 } 989 case MOV_TRAK_VIDEO: { 990 int i, entry; 991 int flag, start, count_flag, end, palette_count, gray; 992 int hdr_ptr = 76; // the byte just after depth 993 unsigned char *palette_map; 994 sh_video_t* sh=new_sh_video(demuxer,priv->track_db); 995 int depth; 996 sh->format=trak->fourcc; 997 998 // crude video delay from editlist0 hack ::atm 999 if(trak->editlist_size>=1) { 1000 if(trak->editlist[0].pos == -1) { 1001 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 1002 dprintf("MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay); 1003 } 1004 } 1005 1006 if (trak->stdata_len < 78) { 1007 dprintf("MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", 1008 trak->stdata_len); 1009 break; 1010 } 1011 depth = trak->stdata[75] | (trak->stdata[74] << 8); 1012 // stdata[]: 1013 // 8 short version 1014 // 10 short revision 1015 // 12 int vendor_id 1016 // 16 int temporal_quality 1017 // 20 int spatial_quality 1018 // 24 short width 1019 // 26 short height 1020 // 28 int h_dpi 1021 // 32 int v_dpi 1022 // 36 int 0 1023 // 40 short frames_per_sample 1024 // 42 char[4] compressor_name 1025 // 74 short depth 1026 // 76 short color_table_id 1027 // additional atoms may follow, 1028 // eg esds atom from .MP4 files 1029 // 78 int atom size 1030 // 82 char[4] atom type 1031 // 86 ... atom data 1032 1033 { ImageDescription* id=malloc(8+trak->stdata_len); // safe 1034 trak->desc=id; 1035 id->idSize=8+trak->stdata_len; 1036 // id->cType=bswap_32(trak->fourcc); 1037 id->cType=le2me_32(trak->fourcc); 1038 id->version=char2short(trak->stdata,8); 1039 id->revisionLevel=char2short(trak->stdata,10); 1040 id->vendor=char2int(trak->stdata,12); 1041 id->temporalQuality=char2int(trak->stdata,16); 1042 id->spatialQuality=char2int(trak->stdata,20); 1043 id->width=char2short(trak->stdata,24); 1044 id->height=char2short(trak->stdata,26); 1045 id->hRes=char2int(trak->stdata,28); 1046 id->vRes=char2int(trak->stdata,32); 1047 id->dataSize=char2int(trak->stdata,36); 1048 id->frameCount=char2short(trak->stdata,40); 1049 memcpy(&id->name,trak->stdata+42,32); 1050 id->depth=char2short(trak->stdata,74); 1051 id->clutID=char2short(trak->stdata,76); 1052 if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); 1053 sh->ImageDesc=id; 1054 #if 0 1055 { FILE *f=fopen("ImageDescription","wb"); 1056 fwrite(id,id->idSize,1,f); 1057 fclose(f); 1058 } 1059 #endif 1060 } 1061 1062 if(trak->stdata_len >= 86) { // extra atoms found 1063 int pos=78; 1064 int atom_len; 1065 while(pos+8<=trak->stdata_len && 1066 (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ 1067 switch(char2int(trak->stdata,pos+4)) { // switch atom type 1068 case MOV_FOURCC('g','a','m','a'): 1069 // intfp with gamma value at which movie was captured 1070 // can be used to gamma correct movie display 1071 dprintf( "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", 1072 atom_len); 1073 break; 1074 case MOV_FOURCC('f','i','e','l'): 1075 // 2 char-values (8bit int) that specify field handling 1076 // see the Apple's QuickTime Fileformat PDF for more info 1077 dprintf( "MOV: Found unsupported Field-Handling movie atom (%d)!\n", 1078 atom_len); 1079 break; 1080 case MOV_FOURCC('m','j','q','t'): 1081 // Motion-JPEG default quantization table 1082 dprintf( "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n", 1083 atom_len); 1084 break; 1085 case MOV_FOURCC('m','j','h','t'): 1086 // Motion-JPEG default huffman table 1087 dprintf( "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n", 1088 atom_len); 1089 break; 1090 case MOV_FOURCC('e','s','d','s'): 1091 // MPEG4 Elementary Stream Descriptor header 1092 dprintf( "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len); 1093 // add code here to save esds header of length atom_len-8 1094 // beginning at stdata[86] to some variable to pass it 1095 // on to the decoder ::atmos 1096 if(atom_len > 8) { 1097 esds_t esds; 1098 if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) { 1099 1100 if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain || 1101 esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial || 1102 esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422) 1103 sh->format=mmioFOURCC('m', 'p', 'g', '2'); 1104 else if(esds.objectTypeId==MP4OTI_MPEG1Visual) 1105 sh->format=mmioFOURCC('m', 'p', 'g', '1'); 1106 1107 // dump away the codec specific configuration for the AAC decoder 1108 trak->stream_header_len = esds.decoderConfigLen; 1109 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1110 memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len); 1111 } 1112 mp4_free_esds(&esds); // freeup esds mem 1113 } 1114 break; 1115 case MOV_FOURCC('a','v','c','C'): 1116 // AVC decoder configuration record 1117 dprintf( "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); 1118 if(atom_len > 8) { 1119 int i, poffs, cnt; 1120 // Parse some parts of avcC, just for fun :) 1121 // real parsing is done by avc1 decoder 1122 dprintf( "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); 1123 if (*(trak->stdata+pos+8) != 1) 1124 dprintf( "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); 1125 dprintf( "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); 1126 dprintf( "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); 1127 dprintf( "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); 1128 dprintf( "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1); 1129 dprintf( "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); 1130 poffs = pos + 14; 1131 for (i = 0; i < cnt; i++) { 1132 dprintf( "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1133 poffs += BE_16(trak->stdata+poffs) + 2; 1134 } 1135 dprintf( "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); 1136 poffs++; 1137 for (i = 0; i < cnt; i++) { 1138 dprintf( "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1139 poffs += BE_16(trak->stdata+poffs) + 2; 1140 } 1141 // Copy avcC for the AVC decoder 1142 // This data will be put in extradata below, where BITMAPINFOHEADER is created 1143 trak->stream_header_len = atom_len-8; 1144 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1145 memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); 1146 } 1147 break; 1148 case MOV_FOURCC('d','2','6','3'): 1149 dprintf( "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len); 1150 if (atom_len>10) 1151 dprintf( "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]); 1152 break; 1153 case 0: 1154 break; 1155 default: 1156 dprintf( "MOV: Found unknown movie atom %c%c%c%c (%d)!\n", 1157 trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7], 1158 atom_len); 1159 } 1160 if(atom_len<8) break; 1161 pos+=atom_len; 1162 // printf("pos=%d max=%d\n",pos,trak->stdata_len); 1163 } 1164 } 1165 sh->fps=trak->timescale/ 1166 ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1); 1167 sh->frametime=1.0f/sh->fps; 1168 1169 sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8); 1170 sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8); 1171 // if image size is zero, fallback to display size 1172 if(!sh->disp_w && !sh->disp_h) { 1173 sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); 1174 sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); 1175 } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){ 1176 // codec and display width differ... use display one for aspect 1177 sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8); 1178 sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8); 1179 } 1180 1181 if(depth>32+8) printf("*** depth = 0x%X\n",depth); 1182 1183 // palettized? 1184 gray = 0; 1185 if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale 1186 if ((depth == 2) || (depth == 4) || (depth == 8)) 1187 palette_count = (1 << depth); 1188 else 1189 palette_count = 0; 1190 1191 // emulate BITMAPINFOHEADER: 1192 if (palette_count) 1193 { 1194 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1195 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1196 sh->bih->biSize=40 + palette_count * 4; 1197 // fetch the relevant fields 1198 flag = BE_16(&trak->stdata[hdr_ptr]); 1199 hdr_ptr += 2; 1200 start = BE_32(&trak->stdata[hdr_ptr]); 1201 hdr_ptr += 4; 1202 count_flag = BE_16(&trak->stdata[hdr_ptr]); 1203 hdr_ptr += 2; 1204 end = BE_16(&trak->stdata[hdr_ptr]); 1205 hdr_ptr += 2; 1206 palette_map = (unsigned char *)sh->bih + 40; 1207 dprintf( "Allocated %d entries for palette\n", 1208 palette_count); 1209 dprintf( "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n", 1210 start, end, count_flag, flag); 1211 1212 /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/ 1213 1214 // load default palette 1215 if (flag & 0x08) 1216 { 1217 if (gray) 1218 { 1219 dprintf( "Using default QT grayscale palette\n"); 1220 if (palette_count == 16) 1221 memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4); 1222 else if (palette_count == 256) { 1223 memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4); 1224 if (trak->fourcc == mmioFOURCC('c','v','i','d')) { 1225 int i; 1226 // Hack for grayscale CVID, negative palette 1227 // If you have samples where this is not required contact me (rxt) 1228 dprintf( "MOV: greyscale cvid with default palette," 1229 " enabling negative palette hack.\n"); 1230 for (i = 0; i < 256 * 4; i++) 1231 palette_map[i] = palette_map[i] ^ 0xff; 1232 } 1233 } 1234 } 1235 else 1236 { 1237 dprintf( "Using default QT colour palette\n"); 1238 if (palette_count == 4) 1239 memcpy(palette_map, qt_default_palette_4, 4 * 4); 1240 else if (palette_count == 16) 1241 memcpy(palette_map, qt_default_palette_16, 16 * 4); 1242 else if (palette_count == 256) 1243 memcpy(palette_map, qt_default_palette_256, 256 * 4); 1244 } 1245 } 1246 // load palette from file 1247 else 1248 { 1249 dprintf( "Loading palette from file\n"); 1250 for (i = start; i <= end; i++) 1251 { 1252 entry = BE_16(&trak->stdata[hdr_ptr]); 1253 hdr_ptr += 2; 1254 // apparently, if count_flag is set, entry is same as i 1255 if (count_flag & 0x8000) 1256 entry = i; 1257 // only care about top 8 bits of 16-bit R, G, or B value 1258 if (entry <= palette_count && entry >= 0) 1259 { 1260 palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0]; 1261 palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2]; 1262 palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4]; 1263 dprintf("QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n", 1264 entry, palette_count, 1265 palette_map[entry * 4 + 2], 1266 palette_map[entry * 4 + 1], 1267 palette_map[entry * 4 + 0]); 1268 } 1269 else 1270 dprintf( "QT palette: skipped entry (out of count): %d of %d\n", 1271 entry, palette_count); 1272 hdr_ptr += 6; 795 1273 } 796 1274 } 797 1275 } 1276 else 1277 { 1278 if (trak->fourcc == mmioFOURCC('a','v','c','1')) { 1279 if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADERw)) { 1280 dprintf("Invalid extradata size %d, skipping\n"); 1281 trak->stream_header_len = 0; 1282 } 1283 1284 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1285 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1286 sh->bih->biSize=40 + trak->stream_header_len; 1287 memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len); 1288 free (trak->stream_header); 1289 trak->stream_header_len = 0; 1290 trak->stream_header = NULL; 1291 } else { 1292 sh->bih=malloc(sizeof(BITMAPINFOHEADERw)); 1293 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw)); 1294 sh->bih->biSize=40; 1295 } 1296 } 1297 sh->bih->biWidth=sh->disp_w; 1298 sh->bih->biHeight=sh->disp_h; 1299 sh->bih->biPlanes=0; 1300 sh->bih->biBitCount=depth; 1301 sh->bih->biCompression=trak->fourcc; 1302 sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; 1303 1304 dprintf( "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount); 1305 if(trak->tkdata_len>81) 1306 dprintf( "Display size: %d x %d\n", 1307 trak->tkdata[77]|(trak->tkdata[76]<<8), 1308 trak->tkdata[81]|(trak->tkdata[80]<<8)); 1309 dprintf( "Fourcc: %.4s Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43); 1310 1311 // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ 1312 // // (auto)selected video track: 1313 // demuxer->video->id=priv->track_db; 1314 // demuxer->video->sh=sh; sh->ds=demuxer->video; 1315 // } 1316 break; 798 1317 } 799 800 switch (version) { 801 case 0: 802 adjust = 0; break; 803 case 1: 804 adjust = 48; break; 805 case 2: 806 adjust = 68; break; 1318 case MOV_TRAK_GENERIC: 1319 if (trak->fourcc == mmioFOURCC('m','p','4','s') || 1320 trak->fourcc == mmioFOURCC('t','x','3','g') || 1321 trak->fourcc == mmioFOURCC('t','e','x','t')) { 1322 sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db); 1323 if (trak->fourcc == mmioFOURCC('m','p','4','s')) 1324 init_vobsub(sh, trak); 1325 else 1326 sh->type = 't'; 1327 } else 1328 dprintf("Generic track - not completely understood! (id: %d)\n", 1329 trak->id); 1330 /* XXX: Also this contains the FLASH data */ 1331 #if 0 1332 { 1333 int pos = stream_tell(demuxer->stream); 1334 int i; 1335 int fd; 1336 char name[20]; 1337 1338 for (i=0; i<trak->samples_size; i++) 1339 { 1340 char buf[trak->samples[i].size]; 1341 stream_seek(demuxer->stream, trak->samples[i].pos); 1342 snprintf((char *)&name[0], 20, "samp%d", i); 1343 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1344 stream_read(demuxer->stream, &buf[0], trak->samples[i].size); 1345 write(fd, &buf[0], trak->samples[i].size); 1346 close(fd); 1347 } 1348 for (i=0; i<trak->chunks_size; i++) 1349 { 1350 char buf[trak->length]; 1351 stream_seek(demuxer->stream, trak->chunks[i].pos); 1352 snprintf((char *)&name[0], 20, "chunk%d", i); 1353 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1354 stream_read(demuxer->stream, &buf[0], trak->length); 1355 write(fd, &buf[0], trak->length); 1356 close(fd); 1357 } 1358 if (trak->samplesize > 0) 1359 { 1360 char *buf; 1361 1362 buf = malloc(trak->samplesize); 1363 stream_seek(demuxer->stream, trak->chunks[0].pos); 1364 snprintf((char *)&name[0], 20, "trak%d", trak->id); 1365 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1366 stream_read(demuxer->stream, buf, trak->samplesize); 1367 write(fd, buf, trak->samplesize); 1368 close(fd); 1369 } 1370 stream_seek(demuxer->stream, pos); 1371 } 1372 #endif 1373 break; 807 1374 default: 808 dprintf( " MOV: unknown sound atom version (%d); may not work!\n", version);809 adjust = 68;1375 dprintf( "Unknown track type found (type: %d)\n", trak->type); 1376 break; 810 1377 } 811 if (trak->stdata_len >= 36 + adjust) { 812 int atom_len = char2int(trak->stdata,28+adjust); 813 switch(char2int(trak->stdata,32+adjust)) { // atom type 814 case MOV_FOURCC('e','s','d','s'): { 815 dprintf( "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len); 816 if(atom_len > 8) { 817 esds_t esds; 818 if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) { 819 /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html), 820 so perform some extra checks to be sure that this is really vorbis audio */ 821 if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8) 822 { 823 //vorbis audio 824 unsigned char *buf[3]; 825 unsigned short sizes[3]; 826 int offset, len, k; 827 unsigned char *ptr = esds.decoderConfig; 828 829 if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout 830 831 offset = len = 0; 832 for(k = 0; k < 3; k++) 833 { 834 sizes[k] = (ptr[offset]<<8) | ptr[offset+1]; 835 len += sizes[k]; 836 offset += 2; 837 if(offset + sizes[k] > esds.decoderConfigLen) 838 { 839 dprintf("MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen); 840 goto quit_vorbis_block; 841 } 842 buf[k] = malloc(sizes[k]); 843 if(!buf[k]) goto quit_vorbis_block; 844 memcpy(buf[k], &ptr[offset], sizes[k]); 845 offset += sizes[k]; 846 } 847 848 sh->codecdata_len = len + len/255 + 64; 849 sh->codecdata = malloc(sh->codecdata_len); 850 ptr = sh->codecdata; 851 852 ptr[0] = 2; 853 offset = 1; 854 offset += store_ughvlc(&ptr[offset], sizes[0]); 855 offset += store_ughvlc(&ptr[offset], sizes[1]); 856 for(k = 0; k < 3; k++) 857 { 858 memcpy(&ptr[offset], buf[k], sizes[k]); 859 offset += sizes[k]; 860 } 861 862 sh->codecdata_len = offset; 863 sh->codecdata = realloc(sh->codecdata, offset); 864 dprintf("demux_mov, vorbis extradata size: %d\n", offset); 865 is_vorbis = 1; 866 quit_vorbis_block: 867 sh->format = mmioFOURCC('v', 'r', 'b', 's'); 868 } 869 sh->i_bps = esds.avgBitrate/8; 870 871 // printf("######## audio format = %d ########\n",esds.objectTypeId); 872 if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3) 873 sh->format=0x55; // .mp3 874 if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2 875 sh->format=mmioFOURCC('Q', 'c', 'l', 'p'); 876 trak->nchannels=sh->channels=1; 877 trak->samplebytes=sh->samplesize=1; 878 } 879 880 // dump away the codec specific configuration for the AAC decoder 881 if(esds.decoderConfigLen){ 882 if( (esds.decoderConfig[0]>>3) == 29 ) 883 sh->format = 0x1d61346d; // request multi-channel mp3 decoder 884 if(!is_vorbis) 885 { 886 sh->codecdata_len = esds.decoderConfigLen; 887 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 888 memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len); 889 } 890 } 891 } 892 mp4_free_esds(&esds); // freeup esds mem 893 #if 0 894 { FILE* f=fopen("esds.dat","wb"); 895 fwrite(&trak->stdata[36],atom_len-8,1,f); 896 fclose(f); } 897 #endif 898 } 899 } break; 900 case MOV_FOURCC('a','l','a','c'): { 901 dprintf( "MOV: Found alac atom (%d)!\n", atom_len); 902 if(atom_len > 8) { 903 // copy all the atom (not only payload) for lavc alac decoder 904 sh->codecdata_len = atom_len; 905 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len); 906 memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len); 907 } 908 } break; 909 case MOV_FOURCC('d','a','m','r'): 910 dprintf( "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len); 911 if (atom_len>14) { 912 dprintf( "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]); 913 dprintf( "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]); 914 dprintf( "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]); 915 } 916 break; 917 default: 918 dprintf( "MOV: Found unknown audio atom %c%c%c%c (%d)!\n", 919 trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], 920 atom_len); 921 } 922 } 923 dprintf( "Fourcc: %.4s\n",(char *)&trak->fourcc); 924 #if 0 925 { FILE* f=fopen("stdata.dat","wb"); 926 fwrite(trak->stdata,trak->stdata_len,1,f); 927 fclose(f); } 928 { FILE* f=fopen("tkdata.dat","wb"); 929 fwrite(trak->tkdata,trak->tkdata_len,1,f); 930 fclose(f); } 931 #endif 932 // Emulate WAVEFORMATEX struct: 933 sh->wf=malloc(sizeof(WAVEFORMATEX) + (is_vorbis ? sh->codecdata_len : 0)); 934 memset(sh->wf,0,sizeof(WAVEFORMATEX)); 935 sh->wf->nChannels=sh->channels; 936 sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19]; 937 // sh->wf->nSamplesPerSec=trak->timescale; 938 sh->wf->nSamplesPerSec=sh->samplerate; 939 if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ 940 //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2 941 sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec* 942 char2int(trak->stdata,32)+char2int(trak->stdata,28)/2) 943 /char2int(trak->stdata,28); 944 sh->wf->nBlockAlign=char2int(trak->stdata,36); 945 } else { 946 sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8; 947 // workaround for ms11 ima4 948 if (sh->format == 0x1100736d && trak->stdata_len >= 36) 949 sh->wf->nBlockAlign=char2int(trak->stdata,36); 950 } 951 if(is_vorbis && sh->codecdata_len) 952 { 953 memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len); 954 sh->wf->cbSize = sh->codecdata_len; 955 } 956 // Selection: 957 // if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ 958 // // (auto)selected audio track: 959 // demuxer->audio->id=priv->track_db; 960 // demuxer->audio->sh=sh; sh->ds=demuxer->audio; 961 // } 1378 dprintf( "--------------\n"); 1379 priv->track_db++; 1380 trak=NULL; 962 1381 break; 963 1382 } 964 case MOV_TRAK_VIDEO: { 965 int i, entry; 966 int flag, start, count_flag, end, palette_count, gray; 967 int hdr_ptr = 76; // the byte just after depth 968 unsigned char *palette_map; 969 sh_video_t* sh=new_sh_video(demuxer,priv->track_db); 970 int depth; 971 sh->format=trak->fourcc; 972 973 // crude video delay from editlist0 hack ::atm 974 if(trak->editlist_size>=1) { 975 if(trak->editlist[0].pos == -1) { 976 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 977 dprintf("MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay); 978 } 979 } 980 981 if (trak->stdata_len < 78) { 982 dprintf("MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", 983 trak->stdata_len); 1383 #ifndef HAVE_ZLIB 1384 case MOV_FOURCC('c','m','o','v'): { 1385 dprintf("MOV: got compressed header but have no zlib\n"); 1386 return; 1387 } 1388 #else 1389 case MOV_FOURCC('m','o','o','v'): 1390 case MOV_FOURCC('c','m','o','v'): { 1391 // dprintf(MSGTR_MOVcomprhdr); 1392 lschunks(demuxer,level+1,pos+len,NULL); 1393 break; 1394 } 1395 case MOV_FOURCC('d','c','o','m'): { 1396 // int temp=stream_read_dword(demuxer->stream); 1397 unsigned int algo=be2me_32(stream_read_dword(demuxer->stream)); 1398 dprintf( "Compressed header uses %.4s algo!\n",(char *)&algo); 1399 break; 1400 } 1401 case MOV_FOURCC('c','m','v','d'): { 1402 // int temp=stream_read_dword(demuxer->stream); 1403 unsigned int moov_sz=stream_read_dword(demuxer->stream); 1404 unsigned int cmov_sz=len-4; 1405 unsigned char* cmov_buf; 1406 unsigned char* moov_buf; 1407 int zret; 1408 z_stream zstrm; 1409 stream_t* backup; 1410 1411 if (moov_sz > 0xffffffff - 16) { 1412 dprintf("Invalid cmvd atom size %d\n", moov_sz); 984 1413 break; 985 1414 } 986 depth = trak->stdata[75] | (trak->stdata[74] << 8); 987 // stdata[]: 988 // 8 short version 989 // 10 short revision 990 // 12 int vendor_id 991 // 16 int temporal_quality 992 // 20 int spatial_quality 993 // 24 short width 994 // 26 short height 995 // 28 int h_dpi 996 // 32 int v_dpi 997 // 36 int 0 998 // 40 short frames_per_sample 999 // 42 char[4] compressor_name 1000 // 74 short depth 1001 // 76 short color_table_id 1002 // additional atoms may follow, 1003 // eg esds atom from .MP4 files 1004 // 78 int atom size 1005 // 82 char[4] atom type 1006 // 86 ... atom data 1007 1008 { ImageDescription* id=malloc(8+trak->stdata_len); // safe 1009 trak->desc=id; 1010 id->idSize=8+trak->stdata_len; 1011 // id->cType=bswap_32(trak->fourcc); 1012 id->cType=le2me_32(trak->fourcc); 1013 id->version=char2short(trak->stdata,8); 1014 id->revisionLevel=char2short(trak->stdata,10); 1015 id->vendor=char2int(trak->stdata,12); 1016 id->temporalQuality=char2int(trak->stdata,16); 1017 id->spatialQuality=char2int(trak->stdata,20); 1018 id->width=char2short(trak->stdata,24); 1019 id->height=char2short(trak->stdata,26); 1020 id->hRes=char2int(trak->stdata,28); 1021 id->vRes=char2int(trak->stdata,32); 1022 id->dataSize=char2int(trak->stdata,36); 1023 id->frameCount=char2short(trak->stdata,40); 1024 memcpy(&id->name,trak->stdata+42,32); 1025 id->depth=char2short(trak->stdata,74); 1026 id->clutID=char2short(trak->stdata,76); 1027 if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78); 1028 sh->ImageDesc=id; 1415 cmov_buf=malloc(cmov_sz); 1416 moov_buf=malloc(moov_sz+16); 1417 dprintf( "Compressed header size: %d / %d\n",cmov_sz,moov_sz); 1418 1419 stream_read(demuxer->stream,cmov_buf,cmov_sz); 1420 1421 zstrm.zalloc = (alloc_func)0; 1422 zstrm.zfree = (free_func)0; 1423 zstrm.opaque = (voidpf)0; 1424 zstrm.next_in = cmov_buf; 1425 zstrm.avail_in = cmov_sz; 1426 zstrm.next_out = moov_buf; 1427 zstrm.avail_out = moov_sz; 1428 1429 zret = inflateInit(&zstrm); 1430 if (zret != Z_OK) 1431 { dprintf( "QT cmov: inflateInit err %d\n",zret); 1432 return; 1433 } 1434 zret = inflate(&zstrm, Z_NO_FLUSH); 1435 if ((zret != Z_OK) && (zret != Z_STREAM_END)) 1436 { dprintf( "QT cmov inflate: ERR %d\n",zret); 1437 return; 1438 } 1029 1439 #if 0 1030 { FILE *f=fopen("ImageDescription","wb"); 1031 fwrite(id,id->idSize,1,f); 1032 fclose(f); 1440 else { 1441 FILE *DecOut; 1442 DecOut = fopen("Out.bin", "w"); 1443 fwrite(moov_buf, 1, moov_sz, DecOut); 1444 fclose(DecOut); 1033 1445 } 1034 1446 #endif 1035 } 1036 1037 if(trak->stdata_len >= 86) { // extra atoms found 1038 int pos=78; 1039 int atom_len; 1040 while(pos+8<=trak->stdata_len && 1041 (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){ 1042 switch(char2int(trak->stdata,pos+4)) { // switch atom type 1043 case MOV_FOURCC('g','a','m','a'): 1044 // intfp with gamma value at which movie was captured 1045 // can be used to gamma correct movie display 1046 dprintf( "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n", 1047 atom_len); 1048 break; 1049 case MOV_FOURCC('f','i','e','l'): 1050 // 2 char-values (8bit int) that specify field handling 1051 // see the Apple's QuickTime Fileformat PDF for more info 1052 dprintf( "MOV: Found unsupported Field-Handling movie atom (%d)!\n", 1053 atom_len); 1054 break; 1055 case MOV_FOURCC('m','j','q','t'): 1056 // Motion-JPEG default quantization table 1057 dprintf( "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n", 1058 atom_len); 1059 break; 1060 case MOV_FOURCC('m','j','h','t'): 1061 // Motion-JPEG default huffman table 1062 dprintf( "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n", 1063 atom_len); 1064 break; 1065 case MOV_FOURCC('e','s','d','s'): 1066 // MPEG4 Elementary Stream Descriptor header 1067 dprintf( "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len); 1068 // add code here to save esds header of length atom_len-8 1069 // beginning at stdata[86] to some variable to pass it 1070 // on to the decoder ::atmos 1071 if(atom_len > 8) { 1072 esds_t esds; 1073 if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) { 1074 1075 if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain || 1076 esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial || 1077 esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422) 1078 sh->format=mmioFOURCC('m', 'p', 'g', '2'); 1079 else if(esds.objectTypeId==MP4OTI_MPEG1Visual) 1080 sh->format=mmioFOURCC('m', 'p', 'g', '1'); 1081 1082 // dump away the codec specific configuration for the AAC decoder 1083 trak->stream_header_len = esds.decoderConfigLen; 1084 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1085 memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len); 1447 if(moov_sz != zstrm.total_out) 1448 dprintf( "Warning! moov size differs cmov: %d zlib: %ld\n",moov_sz,zstrm.total_out); 1449 zret = inflateEnd(&zstrm); 1450 1451 backup=demuxer->stream; 1452 demuxer->stream=new_memory_stream(moov_buf,moov_sz); 1453 stream_skip(demuxer->stream,8); 1454 lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' 1455 //free_stream(demuxer->stream); 1456 demuxer->stream=backup; 1457 free(cmov_buf); 1458 free(moov_buf); 1459 break; 1460 } 1461 #endif 1462 case MOV_FOURCC('u','d','t','a'): 1463 { 1464 unsigned int udta_id; 1465 off_t udta_len; 1466 off_t udta_size = len; 1467 1468 dprintf( "mov: user data record found\n"); 1469 dprintf( "Quicktime Clip Info:\n"); 1470 1471 while((len > 8) && (udta_size > 8)) 1472 { 1473 udta_len = stream_read_dword(demuxer->stream); 1474 udta_id = stream_read_dword(demuxer->stream); 1475 udta_size -= 8; 1476 dprintf( "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len); 1477 switch (udta_id) 1478 { 1479 case MOV_FOURCC(0xa9,'c','p','y'): 1480 case MOV_FOURCC(0xa9,'d','a','y'): 1481 case MOV_FOURCC(0xa9,'d','i','r'): 1482 /* 0xa9,'e','d','1' - '9' : edit timestamps */ 1483 case MOV_FOURCC(0xa9,'f','m','t'): 1484 case MOV_FOURCC(0xa9,'i','n','f'): 1485 case MOV_FOURCC(0xa9,'p','r','d'): 1486 case MOV_FOURCC(0xa9,'p','r','f'): 1487 case MOV_FOURCC(0xa9,'r','e','q'): 1488 case MOV_FOURCC(0xa9,'s','r','c'): 1489 case MOV_FOURCC('n','a','m','e'): 1490 case MOV_FOURCC(0xa9,'n','a','m'): 1491 case MOV_FOURCC(0xa9,'A','R','T'): 1492 case MOV_FOURCC(0xa9,'c','m','t'): 1493 case MOV_FOURCC(0xa9,'a','u','t'): 1494 case MOV_FOURCC(0xa9,'s','w','r'): 1495 { 1496 off_t text_len = stream_read_word(demuxer->stream); 1497 char text[text_len+2+1]; 1498 stream_read(demuxer->stream, (char *)&text, text_len+2); 1499 text[text_len+2] = 0x0; 1500 switch(udta_id) 1501 { 1502 case MOV_FOURCC(0xa9,'a','u','t'): 1503 demux_info_add(demuxer, "author", &text[2]); 1504 dprintf( " Author: %s\n", &text[2]); 1505 break; 1506 case MOV_FOURCC(0xa9,'c','p','y'): 1507 demux_info_add(demuxer, "copyright", &text[2]); 1508 dprintf( " Copyright: %s\n", &text[2]); 1509 break; 1510 case MOV_FOURCC(0xa9,'i','n','f'): 1511 dprintf( " Info: %s\n", &text[2]); 1512 break; 1513 case MOV_FOURCC('n','a','m','e'): 1514 case MOV_FOURCC(0xa9,'n','a','m'): 1515 demux_info_add(demuxer, "name", &text[2]); 1516 dprintf( " Name: %s\n", &text[2]); 1517 break; 1518 case MOV_FOURCC(0xa9,'A','R','T'): 1519 dprintf( " Artist: %s\n", &text[2]); 1520 break; 1521 case MOV_FOURCC(0xa9,'d','i','r'): 1522 dprintf( " Director: %s\n", &text[2]); 1523 break; 1524 case MOV_FOURCC(0xa9,'c','m','t'): 1525 demux_info_add(demuxer, "comments", &text[2]); 1526 dprintf( " Comment: %s\n", &text[2]); 1527 break; 1528 case MOV_FOURCC(0xa9,'r','e','q'): 1529 dprintf( " Requirements: %s\n", &text[2]); 1530 break; 1531 case MOV_FOURCC(0xa9,'s','w','r'): 1532 demux_info_add(demuxer, "encoder", &text[2]); 1533 dprintf( " Software: %s\n", &text[2]); 1534 break; 1535 case MOV_FOURCC(0xa9,'d','a','y'): 1536 dprintf( " Creation timestamp: %s\n", &text[2]); 1537 break; 1538 case MOV_FOURCC(0xa9,'f','m','t'): 1539 dprintf( " Format: %s\n", &text[2]); 1540 break; 1541 case MOV_FOURCC(0xa9,'p','r','d'): 1542 dprintf( " Producer: %s\n", &text[2]); 1543 break; 1544 case MOV_FOURCC(0xa9,'p','r','f'): 1545 dprintf( " Performer(s): %s\n", &text[2]); 1546 break; 1547 case MOV_FOURCC(0xa9,'s','r','c'): 1548 dprintf( " Source providers: %s\n", &text[2]); 1549 break; 1086 1550 } 1087 mp4_free_esds(&esds); // freeup esds mem 1551 udta_size -= 4+text_len; 1552 break; 1088 1553 } 1089 break; 1090 case MOV_FOURCC('a','v','c','C'): 1091 // AVC decoder configuration record 1092 dprintf( "MOV: AVC decoder configuration record atom (%d)!\n", atom_len); 1093 if(atom_len > 8) { 1094 int i, poffs, cnt; 1095 // Parse some parts of avcC, just for fun :) 1096 // real parsing is done by avc1 decoder 1097 dprintf( "MOV: avcC version: %d\n", *(trak->stdata+pos+8)); 1098 if (*(trak->stdata+pos+8) != 1) 1099 dprintf( "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9)); 1100 dprintf( "MOV: avcC profile: %d\n", *(trak->stdata+pos+9)); 1101 dprintf( "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10)); 1102 dprintf( "MOV: avcC level: %d\n", *(trak->stdata+pos+11)); 1103 dprintf( "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1); 1104 dprintf( "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f)); 1105 poffs = pos + 14; 1106 for (i = 0; i < cnt; i++) { 1107 dprintf( "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1108 poffs += BE_16(trak->stdata+poffs) + 2; 1109 } 1110 dprintf( "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs)); 1111 poffs++; 1112 for (i = 0; i < cnt; i++) { 1113 dprintf( "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs)); 1114 poffs += BE_16(trak->stdata+poffs) + 2; 1115 } 1116 // Copy avcC for the AVC decoder 1117 // This data will be put in extradata below, where BITMAPINFOHEADER is created 1118 trak->stream_header_len = atom_len-8; 1119 trak->stream_header = (unsigned char *)malloc(trak->stream_header_len); 1120 memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len); 1121 } 1122 break; 1123 case MOV_FOURCC('d','2','6','3'): 1124 dprintf( "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len); 1125 if (atom_len>10) 1126 dprintf( "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]); 1127 break; 1128 case 0: 1129 break; 1554 /* some other shits: WLOC - window location, 1555 LOOP - looping style, 1556 SelO - play only selected frames 1557 AllF - play all frames 1558 */ 1559 case MOV_FOURCC('W','L','O','C'): 1560 case MOV_FOURCC('L','O','O','P'): 1561 case MOV_FOURCC('S','e','l','O'): 1562 case MOV_FOURCC('A','l','l','F'): 1130 1563 default: 1131 dprintf( "MOV: Found unknown movie atom %c%c%c%c (%d)!\n", 1132 trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7], 1133 atom_len); 1134 } 1135 if(atom_len<8) break; 1136 pos+=atom_len; 1137 // printf("pos=%d max=%d\n",pos,trak->stdata_len); 1138 } 1139 } 1140 sh->fps=trak->timescale/ 1141 ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1); 1142 sh->frametime=1.0f/sh->fps; 1143 1144 sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8); 1145 sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8); 1146 // if image size is zero, fallback to display size 1147 if(!sh->disp_w && !sh->disp_h) { 1148 sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8); 1149 sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8); 1150 } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){ 1151 // codec and display width differ... use display one for aspect 1152 sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8); 1153 sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8); 1154 } 1155 1156 if(depth>32+8) printf("*** depth = 0x%X\n",depth); 1157 1158 // palettized? 1159 gray = 0; 1160 if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale 1161 if ((depth == 2) || (depth == 4) || (depth == 8)) 1162 palette_count = (1 << depth); 1163 else 1164 palette_count = 0; 1165 1166 // emulate BITMAPINFOHEADER: 1167 if (palette_count) 1168 { 1169 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1170 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + palette_count * 4); 1171 sh->bih->biSize=40 + palette_count * 4; 1172 // fetch the relevant fields 1173 flag = BE_16(&trak->stdata[hdr_ptr]); 1174 hdr_ptr += 2; 1175 start = BE_32(&trak->stdata[hdr_ptr]); 1176 hdr_ptr += 4; 1177 count_flag = BE_16(&trak->stdata[hdr_ptr]); 1178 hdr_ptr += 2; 1179 end = BE_16(&trak->stdata[hdr_ptr]); 1180 hdr_ptr += 2; 1181 palette_map = (unsigned char *)sh->bih + 40; 1182 dprintf( "Allocated %d entries for palette\n", 1183 palette_count); 1184 dprintf( "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n", 1185 start, end, count_flag, flag); 1186 1187 /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/ 1188 1189 // load default palette 1190 if (flag & 0x08) 1191 { 1192 if (gray) 1193 { 1194 dprintf( "Using default QT grayscale palette\n"); 1195 if (palette_count == 16) 1196 memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4); 1197 else if (palette_count == 256) { 1198 memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4); 1199 if (trak->fourcc == mmioFOURCC('c','v','i','d')) { 1200 int i; 1201 // Hack for grayscale CVID, negative palette 1202 // If you have samples where this is not required contact me (rxt) 1203 dprintf( "MOV: greyscale cvid with default palette," 1204 " enabling negative palette hack.\n"); 1205 for (i = 0; i < 256 * 4; i++) 1206 palette_map[i] = palette_map[i] ^ 0xff; 1564 { 1565 if( udta_len>udta_size) 1566 udta_len=udta_size; 1567 { 1568 char dump[udta_len-4]; 1569 stream_read(demuxer->stream, (char *)&dump, udta_len-4-4); 1570 udta_size -= udta_len; 1207 1571 } 1208 1572 } 1209 1573 } 1210 else1211 {1212 dprintf( "Using default QT colour palette\n");1213 if (palette_count == 4)1214 memcpy(palette_map, qt_default_palette_4, 4 * 4);1215 else if (palette_count == 16)1216 memcpy(palette_map, qt_default_palette_16, 16 * 4);1217 else if (palette_count == 256)1218 memcpy(palette_map, qt_default_palette_256, 256 * 4);1219 }1220 1574 } 1221 // load palette from file 1222 else 1223 { 1224 dprintf( "Loading palette from file\n"); 1225 for (i = start; i <= end; i++) 1226 { 1227 entry = BE_16(&trak->stdata[hdr_ptr]); 1228 hdr_ptr += 2; 1229 // apparently, if count_flag is set, entry is same as i 1230 if (count_flag & 0x8000) 1231 entry = i; 1232 // only care about top 8 bits of 16-bit R, G, or B value 1233 if (entry <= palette_count && entry >= 0) 1234 { 1235 palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0]; 1236 palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2]; 1237 palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4]; 1238 dprintf("QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n", 1239 entry, palette_count, 1240 palette_map[entry * 4 + 2], 1241 palette_map[entry * 4 + 1], 1242 palette_map[entry * 4 + 0]); 1243 } 1244 else 1245 dprintf( "QT palette: skipped entry (out of count): %d of %d\n", 1246 entry, palette_count); 1247 hdr_ptr += 6; 1248 } 1249 } 1250 } 1251 else 1252 { 1253 if (trak->fourcc == mmioFOURCC('a','v','c','1')) { 1254 if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADERw)) { 1255 dprintf("Invalid extradata size %d, skipping\n"); 1256 trak->stream_header_len = 0; 1257 } 1258 1259 sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1260 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + trak->stream_header_len); 1261 sh->bih->biSize=40 + trak->stream_header_len; 1262 memcpy(((unsigned char *)sh->bih)+40, trak->stream_header, trak->stream_header_len); 1263 free (trak->stream_header); 1264 trak->stream_header_len = 0; 1265 trak->stream_header = NULL; 1266 } else { 1267 sh->bih=malloc(sizeof(BITMAPINFOHEADERw)); 1268 memset(sh->bih,0,sizeof(BITMAPINFOHEADERw)); 1269 sh->bih->biSize=40; 1270 } 1271 } 1272 sh->bih->biWidth=sh->disp_w; 1273 sh->bih->biHeight=sh->disp_h; 1274 sh->bih->biPlanes=0; 1275 sh->bih->biBitCount=depth; 1276 sh->bih->biCompression=trak->fourcc; 1277 sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight; 1278 1279 dprintf( "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount); 1280 if(trak->tkdata_len>81) 1281 dprintf( "Display size: %d x %d\n", 1282 trak->tkdata[77]|(trak->tkdata[76]<<8), 1283 trak->tkdata[81]|(trak->tkdata[80]<<8)); 1284 dprintf( "Fourcc: %.4s Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43); 1285 1286 // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ 1287 // // (auto)selected video track: 1288 // demuxer->video->id=priv->track_db; 1289 // demuxer->video->sh=sh; sh->ds=demuxer->video; 1290 // } 1575 break; 1576 } /* eof udta */ 1577 default: 1578 id = be2me_32(id); 1579 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 1580 } /* endof switch */ 1581 } /* endof else */ 1582 1583 pos+=len+8; 1584 if(pos>=endpos) break; 1585 if(!stream_seek(demuxer->stream,pos)) break; 1586 } 1587 } 1588 1589 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, 1590 off_t pos, off_t len, mov_track_t* trak) 1591 { 1592 switch(id) { 1593 case MOV_FOURCC('m','d','a','t'): { 1594 dprintf("Hmm, strange MOV, parsing mdat in lschunks?\n"); 1595 return -1; 1596 } 1597 case MOV_FOURCC('f','r','e','e'): 1598 case MOV_FOURCC('u','d','t','a'): 1599 /* here not supported :p */ 1600 break; 1601 case MOV_FOURCC('t','k','h','d'): { 1602 dprintf("MOV: %*sTrack header!\n", level, ""); 1603 // read codec data 1604 trak->tkdata_len = len; 1605 trak->tkdata = malloc(trak->tkdata_len); 1606 stream_read(demuxer->stream, trak->tkdata, trak->tkdata_len); 1607 /* 1608 0 1 Version 1609 1 3 Flags 1610 4 4 Creation time 1611 8 4 Modification time 1612 12 4 Track ID 1613 16 4 Reserved 1614 20 4 Duration 1615 24 8 Reserved 1616 32 2 Layer 1617 34 2 Alternate group 1618 36 2 Volume 1619 38 2 Reserved 1620 40 36 Matrix structure 1621 76 4 Track width 1622 80 4 Track height 1623 */ 1624 dprintf( 1625 "tkhd len=%d ver=%d flags=0x%X id=%d dur=%d lay=%d vol=%d\n", 1626 trak->tkdata_len, trak->tkdata[0], trak->tkdata[1], 1627 char2int(trak->tkdata, 12), // id 1628 char2int(trak->tkdata, 20), // duration 1629 char2short(trak->tkdata, 32), // layer 1630 char2short(trak->tkdata, 36)); // volume 1631 break; 1632 } 1633 case MOV_FOURCC('m','d','h','d'): { 1634 dprintf( "MOV: %*sMedia header!\n", level, ""); 1635 int version = stream_read_char(demuxer->stream); 1636 stream_skip(demuxer->stream, (version == 1) ? 19 : 11); 1637 // read timescale 1638 trak->timescale = stream_read_dword(demuxer->stream); 1639 // read length 1640 if (version == 1) 1641 trak->length = stream_read_qword(demuxer->stream); 1642 else 1643 trak->length = stream_read_dword(demuxer->stream); 1644 break; 1645 } 1646 case MOV_FOURCC('h','d','l','r'): { 1647 unsigned int tmp = stream_read_dword(demuxer->stream); 1648 unsigned int type = stream_read_dword_le(demuxer->stream); 1649 unsigned int subtype = stream_read_dword_le(demuxer->stream); 1650 unsigned int manufact = stream_read_dword_le(demuxer->stream); 1651 unsigned int comp_flags = stream_read_dword(demuxer->stream); 1652 unsigned int comp_mask = stream_read_dword(demuxer->stream); 1653 int len = stream_read_char(demuxer->stream); 1654 char* str = malloc(len + 1); 1655 stream_read(demuxer->stream, str, len); 1656 str[len] = 0; 1657 dprintf( 1658 "MOV: %*sHandler header: %.4s/%.4s (%.4s) %s\n", level, "", 1659 (char *)&type, (char *)&subtype, (char *)&manufact, str); 1660 free(str); 1661 switch(bswap_32(type)) { 1662 case MOV_FOURCC('m','h','l','r'): 1663 trak->media_handler = bswap_32(subtype); 1664 break; 1665 case MOV_FOURCC('d','h','l','r'): 1666 trak->data_handler = bswap_32(subtype); 1667 break; 1668 default: 1669 dprintf( 1670 "MOV: unknown handler class: 0x%X (%.4s)\n", 1671 bswap_32(type), (char *)&type); 1672 } 1673 break; 1674 } 1675 case MOV_FOURCC('v','m','h','d'): { 1676 dprintf("MOV: %*sVideo header!\n", level, ""); 1677 trak->type = MOV_TRAK_VIDEO; 1678 // read video data 1679 break; 1680 } 1681 case MOV_FOURCC('s','m','h','d'): { 1682 dprintf("MOV: %*sSound header!\n", level, ""); 1683 trak->type = MOV_TRAK_AUDIO; 1684 // read audio data 1685 break; 1686 } 1687 case MOV_FOURCC('g','m','h','d'): { 1688 dprintf("MOV: %*sGeneric header!\n", level, ""); 1689 trak->type = MOV_TRAK_GENERIC; 1690 break; 1691 } 1692 case MOV_FOURCC('n','m','h','d'): { 1693 dprintf("MOV: %*sGeneric header!\n", level, ""); 1694 trak->type = MOV_TRAK_GENERIC; 1695 break; 1696 } 1697 case MOV_FOURCC('s','t','s','d'): { 1698 int i = stream_read_dword(demuxer->stream); // temp! 1699 int count = stream_read_dword(demuxer->stream); 1700 dprintf("MOV: %*sDescription list! (cnt:%d)\n", 1701 level, "", count); 1702 for (i = 0; i < count; i++) { 1703 off_t pos = stream_tell(demuxer->stream); 1704 off_t len = stream_read_dword(demuxer->stream); 1705 unsigned int fourcc = stream_read_dword_le(demuxer->stream); 1706 /* some files created with Broadcast 2000 (e.g. ilacetest.mov) 1707 contain raw I420 video but have a yv12 fourcc */ 1708 if (fourcc == mmioFOURCC('y','v','1','2')) 1709 fourcc = mmioFOURCC('I','4','2','0'); 1710 if (len < 8) 1711 break; // error 1712 dprintf("MOV: %*s desc #%d: %.4s (%"PRId64" bytes)\n", level, "", 1713 i, (char *)&fourcc, (int64_t)len - 16); 1714 if (fourcc != trak->fourcc && i) 1715 dprintf("MOW: warning - different fourcc\n"); 1716 // if(!i) 1717 { 1718 trak->fourcc = fourcc; 1719 // read type specific (audio/video/time/text etc) header 1720 // NOTE: trak type is not yet known at this point :((( 1721 trak->stdata_len = len - 8; 1722 trak->stdata = malloc(trak->stdata_len); 1723 stream_read(demuxer->stream, trak->stdata, trak->stdata_len); 1724 } 1725 if (!stream_seek(demuxer->stream, pos + len)) 1726 break; 1727 } 1728 break; 1729 } 1730 case MOV_FOURCC('s','t','t','s'): { 1731 int temp = stream_read_dword(demuxer->stream); 1732 int len = stream_read_dword(demuxer->stream); 1733 int i; 1734 unsigned int pts = 0; 1735 dprintf("MOV: %*sSample duration table! (%d blocks)\n", level, "", 1736 len); 1737 trak->durmap = calloc(len, sizeof(mov_durmap_t)); 1738 trak->durmap_size = len; 1739 for (i = 0; i < len; i++) { 1740 trak->durmap[i].num = stream_read_dword(demuxer->stream); 1741 trak->durmap[i].dur = stream_read_dword(demuxer->stream); 1742 pts += trak->durmap[i].num * trak->durmap[i].dur; 1743 } 1744 if (trak->length != pts) 1745 dprintf( "Warning! pts=%d length=%d\n", 1746 pts, trak->length); 1747 break; 1748 } 1749 case MOV_FOURCC('s','t','s','c'): { 1750 int temp = stream_read_dword(demuxer->stream); 1751 int len = stream_read_dword(demuxer->stream); 1752 int ver = (temp << 24); 1753 int flags = (temp << 16) | (temp << 8) | temp; 1754 int i; 1755 dprintf("MOV: %*sSample->Chunk mapping table! (%d blocks) (ver:%d,flags:%d)\n", level, "", 1756 len, ver, flags); 1757 // read data: 1758 trak->chunkmap_size = len; 1759 trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t)); 1760 for (i = 0; i < len; i++) { 1761 trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1; 1762 trak->chunkmap[i].spc = stream_read_dword(demuxer->stream); 1763 trak->chunkmap[i].sdid = stream_read_dword(demuxer->stream); 1764 } 1765 break; 1766 } 1767 case MOV_FOURCC('s','t','s','z'): { 1768 int temp = stream_read_dword(demuxer->stream); 1769 int ss=stream_read_dword(demuxer->stream); 1770 int ver = (temp << 24); 1771 int flags = (temp << 16) | (temp << 8) | temp; 1772 int entries = stream_read_dword(demuxer->stream); 1773 int i; 1774 dprintf( 1775 "MOV: %*sSample size table! (entries=%d ss=%d) (ver:%d,flags:%d)\n", level, "", 1776 entries, ss, ver, flags); 1777 trak->samplesize = ss; 1778 if (!ss) { 1779 // variable samplesize 1780 trak->samples = realloc_struct(trak->samples, entries, sizeof(mov_sample_t)); 1781 trak->samples_size = entries; 1782 for (i = 0; i < entries; i++) 1783 trak->samples[i].size = stream_read_dword(demuxer->stream); 1784 } 1785 break; 1786 } 1787 case MOV_FOURCC('s','t','c','o'): { 1788 int temp = stream_read_dword(demuxer->stream); 1789 int len = stream_read_dword(demuxer->stream); 1790 int i; 1791 dprintf( 1792 "MOV: %*sChunk offset table! (%d chunks)\n", level, "", 1793 len); 1794 // extend array if needed: 1795 if (len > trak->chunks_size) { 1796 trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t)); 1797 trak->chunks_size = len; 1798 } 1799 // read elements: 1800 for(i = 0; i < len; i++) 1801 trak->chunks[i].pos = stream_read_dword(demuxer->stream); 1802 break; 1803 } 1804 case MOV_FOURCC('c','o','6','4'): { 1805 int temp = stream_read_dword(demuxer->stream); 1806 int len = stream_read_dword(demuxer->stream); 1807 int i; 1808 dprintf( 1809 "MOV: %*s64bit chunk offset table! (%d chunks)\n", level, "", 1810 len); 1811 // extend array if needed: 1812 if (len > trak->chunks_size) { 1813 trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t)); 1814 trak->chunks_size = len; 1815 } 1816 // read elements: 1817 for (i = 0; i < len; i++) { 1818 #ifndef _LARGEFILE_SOURCE 1819 if (stream_read_dword(demuxer->stream) != 0) 1820 dprintf( "Chunk %d has got 64bit address, but you've MPlayer compiled without LARGEFILE support!\n", i); 1821 trak->chunks[i].pos = stream_read_dword(demuxer->stream); 1822 #else 1823 trak->chunks[i].pos = stream_read_qword(demuxer->stream); 1824 #endif 1825 } 1826 break; 1827 } 1828 case MOV_FOURCC('s','t','s','s'): { 1829 int temp = stream_read_dword(demuxer->stream); 1830 int entries = stream_read_dword(demuxer->stream); 1831 int ver = (temp << 24); 1832 int flags = (temp << 16) | (temp<<8) | temp; 1833 int i; 1834 dprintf( 1835 "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "", 1836 entries, ver, flags); 1837 trak->keyframes_size = entries; 1838 trak->keyframes = calloc(entries, sizeof(unsigned int)); 1839 for (i = 0; i < entries; i++) 1840 trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1; 1841 break; 1842 } 1843 case MOV_FOURCC('m','d','i','a'): { 1844 dprintf( "MOV: %*sMedia stream!\n", level, ""); 1845 lschunks(demuxer, level + 1, pos + len, trak); 1846 break; 1847 } 1848 case MOV_FOURCC('m','i','n','f'): { 1849 dprintf( "MOV: %*sMedia info!\n", level, ""); 1850 lschunks(demuxer, level + 1 ,pos + len, trak); 1851 break; 1852 } 1853 case MOV_FOURCC('s','t','b','l'): { 1854 dprintf( "MOV: %*sSample info!\n", level, ""); 1855 lschunks(demuxer, level + 1, pos + len, trak); 1856 break; 1857 } 1858 case MOV_FOURCC('e','d','t','s'): { 1859 dprintf( "MOV: %*sEdit atom!\n", level, ""); 1860 lschunks(demuxer, level + 1, pos + len, trak); 1861 break; 1862 } 1863 case MOV_FOURCC('e','l','s','t'): { 1864 int temp = stream_read_dword(demuxer->stream); 1865 int entries = stream_read_dword(demuxer->stream); 1866 int ver = (temp << 24); 1867 int flags = (temp << 16) | (temp << 8) | temp; 1868 int i; 1869 dprintf( 1870 "MOV: %*sEdit list table (%d entries) (ver:%d,flags:%d)\n", level, "", 1871 entries, ver, flags); 1872 #if 1 1873 trak->editlist_size = entries; 1874 trak->editlist = calloc(trak->editlist_size, sizeof(mov_editlist_t)); 1875 for (i = 0; i < entries; i++) { 1876 int dur = stream_read_dword(demuxer->stream); 1877 int mt = stream_read_dword(demuxer->stream); 1878 int mr = stream_read_dword(demuxer->stream); // 16.16fp 1879 trak->editlist[i].dur = dur; 1880 trak->editlist[i].pos = mt; 1881 trak->editlist[i].speed = mr; 1882 dprintf( 1883 "MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n", level, "", 1884 i, dur, mt, (float)mr/65536.0f); 1885 } 1886 #endif 1887 break; 1888 } 1889 case MOV_FOURCC('c','o','d','e'): { 1890 /* XXX: Implement atom 'code' for FLASH support */ 1891 break; 1892 } 1893 default: 1894 id = be2me_32(id); 1895 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 1896 break; 1897 }//switch(id) 1898 return 0; 1899 } 1900 1901 static demuxer_t* mov_read_header(demuxer_t* demuxer){ 1902 mov_priv_t* priv=demuxer->priv; 1903 int t_no; 1904 int best_a_id=-1, best_a_len=0; 1905 int best_v_id=-1, best_v_len=0; 1906 1907 dprintf( "mov_read_header!\n"); 1908 1909 // Parse header: 1910 stream_reset(demuxer->stream); 1911 if(!stream_seek(demuxer->stream,priv->moov_start)) 1912 { 1913 dprintf("MOV: Cannot seek to the beginning of the Movie header (0x%"PRIx64")\n", 1914 (int64_t)priv->moov_start); 1915 return 0; 1916 } 1917 lschunks(demuxer, 0, priv->moov_end, NULL); 1918 // just in case we have hit eof while parsing... 1919 demuxer->stream->eof = 0; 1920 // dprintf( "--------------\n"); 1921 1922 // find the best (longest) streams: 1923 for(t_no=0;t_no<priv->track_db;t_no++){ 1924 mov_track_t* trak=priv->tracks[t_no]; 1925 int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size; 1926 if(demuxer->a_streams[t_no]){ // need audio 1927 if(len>best_a_len){ best_a_len=len; best_a_id=t_no; } 1928 } 1929 if(demuxer->v_streams[t_no]){ // need video 1930 if(len>best_v_len){ best_v_len=len; best_v_id=t_no; } 1931 } 1932 } 1933 dprintf( "MOV: longest streams: A: #%d (%d samples) V: #%d (%d samples)\n", 1934 best_a_id,best_a_len,best_v_id,best_v_len); 1935 if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id; 1936 if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id; 1937 1938 // setup sh pointers: 1939 if(demuxer->audio->id>=0){ 1940 sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id]; 1941 if(sh){ 1942 demuxer->audio->sh=sh; sh->ds=demuxer->audio; 1943 } else { 1944 dprintf( "MOV: selected audio stream (%d) does not exists\n",demuxer->audio->id); 1945 demuxer->audio->id=-2; 1946 } 1947 } 1948 if(demuxer->video->id>=0){ 1949 sh_video_t* sh=demuxer->v_streams[demuxer->video->id]; 1950 if(sh){ 1951 demuxer->video->sh=sh; sh->ds=demuxer->video; 1952 } else { 1953 dprintf( "MOV: selected video stream (%d) does not exists\n",demuxer->video->id); 1954 demuxer->video->id=-2; 1955 } 1956 } 1957 1958 if(demuxer->sub->id>=0){ 1959 sh_sub_t* sh=demuxer->s_streams[demuxer->sub->id]; 1960 if(sh){ 1961 demuxer->sub->sh=sh; 1962 } else { 1963 dprintf("MOV: selected video stream (%d) does not exists\n",demuxer->video->id); 1964 demuxer->sub->id=-2; 1965 } 1966 } 1967 if(demuxer->video->id<0 && demuxer->audio->id<0) { 1968 /* No AV streams found. Try to find an MPEG stream. */ 1969 for(t_no=0;t_no<priv->track_db;t_no++){ 1970 mov_track_t* trak=priv->tracks[t_no]; 1971 if(trak->media_handler == MOV_FOURCC('M','P','E','G')) { 1972 stream_t *s; 1973 demuxer_t *od; 1974 1975 demuxer->video->id = t_no; 1976 s = new_ds_stream(demuxer->video); 1977 od = demux_open(s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL); 1978 if(od) return new_demuxers_demuxer(od, od, od); 1979 demuxer->video->id = -2; //new linked demuxer couldn't be allocated 1291 1980 break; 1292 1981 } 1293 case MOV_TRAK_GENERIC: 1294 dprintf( "Generic track - not completely understood! (id: %d)\n", 1295 trak->id); 1296 /* XXX: Also this contains the FLASH data */ 1982 } 1983 } 1297 1984 1298 1985 #if 0 1986 if( mp_msg_test(MSGL_DBG3) ){ 1987 for(t_no=0;t_no<priv->track_db;t_no++){ 1988 mov_track_t* trak=priv->tracks[t_no]; 1989 if(trak->type==MOV_TRAK_GENERIC){ 1990 int i; 1991 int fd; 1992 char name[20]; 1993 dprintf( "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size); 1994 for (i=0; i<trak->samples_size; i++) 1299 1995 { 1300 int pos = stream_tell(demuxer->stream); 1301 int i; 1302 int fd; 1303 char name[20]; 1304 1305 for (i=0; i<trak->samples_size; i++) 1996 int len=trak->samples[i].size; 1997 char buf[len]; 1998 stream_seek(demuxer->stream, trak->samples[i].pos); 1999 snprintf(name, 20, "t%02d-s%03d.%s", t_no,i, 2000 (trak->media_handler==MOV_FOURCC('f','l','s','h')) ? 2001 "swf":"dump"); 2002 fd = open(name, O_CREAT|O_WRONLY); 2003 // { int j; 2004 // for(j=0;j<trak->stdata_len-3; j++) 2005 // printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b')); 2006 // } 2007 if( //trak->media_handler==MOV_FOURCC('s','p','r','t') && 2008 trak->stdata_len>=16 && 2009 char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b') 2010 ){ 2011 int newlen=stream_read_dword(demuxer->stream); 2012 #ifdef HAVE_ZLIB 2013 // unzip: 2014 z_stream zstrm; 2015 int zret; 2016 char buf2[newlen]; 2017 2018 len-=4; 2019 stream_read(demuxer->stream, buf, len); 2020 2021 zstrm.zalloc = (alloc_func)0; 2022 zstrm.zfree = (free_func)0; 2023 zstrm.opaque = (voidpf)0; 2024 zstrm.next_in = buf; 2025 zstrm.avail_in = len; 2026 zstrm.next_out = buf2; 2027 zstrm.avail_out = newlen; 2028 2029 zret = inflateInit(&zstrm); 2030 zret = inflate(&zstrm, Z_NO_FLUSH); 2031 if(newlen != zstrm.total_out) 2032 dprintf( "Warning! unzipped frame size differs hdr: %d zlib: %ld\n",newlen,zstrm.total_out); 2033 2034 write(fd, buf2, newlen); 2035 } else { 2036 #else 2037 len-=4; 2038 dprintf( "******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen); 2039 } 1306 2040 { 1307 char buf[trak->samples[i].size]; 1308 stream_seek(demuxer->stream, trak->samples[i].pos); 1309 snprintf((char *)&name[0], 20, "samp%d", i); 1310 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1311 stream_read(demuxer->stream, &buf[0], trak->samples[i].size); 1312 write(fd, &buf[0], trak->samples[i].size); 1313 close(fd); 2041 #endif 2042 stream_read(demuxer->stream, buf, len); 2043 write(fd, buf, len); 1314 2044 } 1315 for (i=0; i<trak->chunks_size; i++) 1316 { 1317 char buf[trak->length]; 1318 stream_seek(demuxer->stream, trak->chunks[i].pos); 1319 snprintf((char *)&name[0], 20, "chunk%d", i); 1320 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1321 stream_read(demuxer->stream, &buf[0], trak->length); 1322 write(fd, &buf[0], trak->length); 1323 close(fd); 1324 } 1325 if (trak->samplesize > 0) 1326 { 1327 char *buf; 1328 1329 buf = malloc(trak->samplesize); 1330 stream_seek(demuxer->stream, trak->chunks[0].pos); 1331 snprintf((char *)&name[0], 20, "trak%d", trak->id); 1332 fd = open((char *)&name[0], O_CREAT|O_WRONLY); 1333 stream_read(demuxer->stream, buf, trak->samplesize); 1334 write(fd, buf, trak->samplesize); 1335 close(fd); 1336 } 1337 stream_seek(demuxer->stream, pos); 2045 close(fd); 1338 2046 } 2047 } 2048 } 2049 } 2050 demuxer->stream->eof = 0; 1339 2051 #endif 1340 break; 1341 default: 1342 dprintf( "Unknown track type found (type: %d)\n", trak->type); 1343 break; 2052 return demuxer; 2053 } 2054 2055 /** 2056 * \brief return the mov track that belongs to a demuxer stream 2057 * \param ds the demuxer stream, may be NULL 2058 * \return the mov track info structure belonging to the stream, 2059 * NULL if not found 2060 */ 2061 static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) { 2062 if (ds && (ds->id >= 0) && (ds->id < priv->track_db)) 2063 return priv->tracks[ds->id]; 2064 return NULL; 2065 } 2066 2067 // return value: 2068 // 0 = EOF or no stream found 2069 // 1 = successfully read a packet 2070 static int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){ 2071 mov_priv_t* priv=demuxer->priv; 2072 mov_track_t* trak=NULL; 2073 float pts; 2074 int x; 2075 off_t pos; 2076 2077 if (ds->eof) return 0; 2078 trak = stream_track(priv, ds); 2079 if (!trak) return 0; 2080 2081 if(trak->samplesize){ 2082 // read chunk: 2083 if(trak->pos>=trak->chunks_size) return 0; // EOF 2084 stream_seek(demuxer->stream,trak->chunks[trak->pos].pos); 2085 pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; 2086 if(trak->samplesize!=1) 2087 { 2088 dprintf( "WARNING! Samplesize(%d) != 1\n", 2089 trak->samplesize); 2090 if((trak->fourcc != MOV_FOURCC('t','w','o','s')) && (trak->fourcc != MOV_FOURCC('s','o','w','t'))) 2091 x=trak->chunks[trak->pos].size*trak->samplesize; 2092 else 2093 x=trak->chunks[trak->pos].size; 2094 } 2095 x=trak->chunks[trak->pos].size; 2096 // printf("X = %d\n", x); 2097 /* the following stuff is audio related */ 2098 if (trak->type == MOV_TRAK_AUDIO){ 2099 if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ 2100 // stsd version 1 - we have audio compression ratio info: 2101 x/=char2int(trak->stdata,28); // samples/packet 2102 // x*=char2int(trak->stdata,32); // bytes/packet 2103 x*=char2int(trak->stdata,36); // bytes/frame 2104 } else { 2105 if(ds->ss_div && ds->ss_mul){ 2106 // workaround for buggy files like 7up-high-traffic-areas.mov, 2107 // with missing stsd v1 header containing compression rate 2108 x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix ! HACK ! 2109 } else { 2110 x*=trak->nchannels; 2111 x*=trak->samplebytes; 2112 } 1344 2113 } 1345 dprintf( "--------------\n"); 1346 priv->track_db++; 1347 trak=NULL; 1348 break; 1349 } 1350 #ifndef HAVE_ZLIB 1351 case MOV_FOURCC('c','m','o','v'): { 1352 dprintf("MOV: got compressed header but have no zlib\n"); 1353 return; 1354 } 1355 #else 1356 case MOV_FOURCC('m','o','o','v'): 1357 case MOV_FOURCC('c','m','o','v'): { 1358 // dprintf(MSGTR_MOVcomprhdr); 1359 lschunks(demuxer,level+1,pos+len,NULL); 1360 break; 1361 } 1362 case MOV_FOURCC('d','c','o','m'): { 1363 // int temp=stream_read_dword(demuxer->stream); 1364 unsigned int algo=be2me_32(stream_read_dword(demuxer->stream)); 1365 dprintf( "Compressed header uses %.4s algo!\n",(char *)&algo); 1366 break; 1367 } 1368 case MOV_FOURCC('c','m','v','d'): { 1369 // int temp=stream_read_dword(demuxer->stream); 1370 unsigned int moov_sz=stream_read_dword(demuxer->stream); 1371 unsigned int cmov_sz=len-4; 1372 unsigned char* cmov_buf; 1373 unsigned char* moov_buf; 1374 int zret; 1375 z_stream zstrm; 1376 stream_t* backup; 1377 1378 if (moov_sz > 0xffffffff - 16) { 1379 dprintf("Invalid cmvd atom size %d\n", moov_sz); 1380 break; 2114 dprintf( "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts); 2115 } /* MOV_TRAK_AUDIO */ 2116 pos=trak->chunks[trak->pos].pos; 2117 } else { 2118 int frame=trak->pos; 2119 // editlist support: 2120 if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){ 2121 // find the right editlist entry: 2122 if(frame<trak->editlist[trak->editlist_pos].start_frame) 2123 trak->editlist_pos=0; 2124 while(trak->editlist_pos<trak->editlist_size-1 && 2125 frame>=trak->editlist[trak->editlist_pos+1].start_frame) 2126 ++trak->editlist_pos; 2127 if(frame>=trak->editlist[trak->editlist_pos].start_frame+ 2128 trak->editlist[trak->editlist_pos].frames) return 0; // EOF 2129 // calc real frame index: 2130 frame-=trak->editlist[trak->editlist_pos].start_frame; 2131 frame+=trak->editlist[trak->editlist_pos].start_sample; 2132 // calc pts: 2133 pts=(float)(trak->samples[frame].pts+ 2134 trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale; 2135 } else { 2136 if(frame>=trak->samples_size) return 0; // EOF 2137 pts=(float)trak->samples[frame].pts/(float)trak->timescale; 2138 } 2139 // read sample: 2140 stream_seek(demuxer->stream,trak->samples[frame].pos); 2141 x=trak->samples[frame].size; 2142 pos=trak->samples[frame].pos; 2143 } 2144 if(trak->pos==0 && trak->stream_header_len>0){ 2145 // we have to append the stream header... 2146 demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len); 2147 memcpy(dp->buffer,trak->stream_header,trak->stream_header_len); 2148 stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x); 2149 free(trak->stream_header); 2150 trak->stream_header = NULL; 2151 trak->stream_header_len = 0; 2152 dp->pts=pts; 2153 dp->flags=0; 2154 dp->pos=pos; // FIXME? 2155 ds_add_packet(ds,dp); 2156 } else 2157 ds_read_packet(ds,demuxer->stream,x,pts,pos,0); 2158 2159 ++trak->pos; 2160 if (demuxer->sub->id >= 0) { 2161 int samplenr = 0; 2162 trak = priv->tracks[demuxer->sub->id]; 2163 while (samplenr < trak->samples_size) { 2164 double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale; 2165 if (subpts >= pts) break; 2166 samplenr++; 2167 } 2168 samplenr--; 2169 if (samplenr < 0) 2170 vo_sub = NULL; 2171 else if (samplenr != priv->current_sub) { 2172 sh_sub_t *sh = demuxer->sub->sh; 2173 off_t pos = trak->samples[samplenr].pos; 2174 int len = trak->samples[samplenr].size; 2175 double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale; 2176 stream_seek(demuxer->stream, pos); 2177 if (sh->type == 'v') 2178 ds_read_packet(demuxer->sub, demuxer->stream, len, subpts, pos, 0); 2179 else { 2180 int i; 2181 char *line = priv->subtext; 2182 stream_skip(demuxer->stream, 2); // size 2183 len -= 2; 2184 if (len < 0) len = 0; 2185 if (len > MOV_MAX_SUBLEN) len = MOV_MAX_SUBLEN; 2186 stream_read(demuxer->stream, priv->subtext, len); 2187 priv->subtext[len] = 0; 2188 priv->subs.lines = 1; 2189 priv->subs.text[0] = &priv->subtext; 2190 while ((line = strchr(line, '\n'))) { 2191 *line++ = 0; 2192 priv->subs.text[priv->subs.lines] = line; 2193 priv->subs.lines++; 2194 } 2195 vo_sub = &priv->subs; 1381 2196 } 1382 cmov_buf=malloc(cmov_sz); 1383 moov_buf=malloc(moov_sz+16); 1384 dprintf( "Compressed header size: %d / %d\n",cmov_sz,moov_sz); 1385 1386 stream_read(demuxer->stream,cmov_buf,cmov_sz); 1387 1388 zstrm.zalloc = (alloc_func)0; 1389 zstrm.zfree = (free_func)0; 1390 zstrm.opaque = (voidpf)0; 1391 zstrm.next_in = cmov_buf; 1392 zstrm.avail_in = cmov_sz; 1393 zstrm.next_out = moov_buf; 1394 zstrm.avail_out = moov_sz; 1395 1396 zret = inflateInit(&zstrm); 1397 if (zret != Z_OK) 1398 { dprintf( "QT cmov: inflateInit err %d\n",zret); 1399 return; 2197 priv->current_sub = samplenr; 2198 } 2199 vo_osd_changed (OSDTYPE_SUBTITLE); 2200 } 2201 2202 return 1; 2203 2204 } 2205 2206 static float mov_seek_track(mov_track_t* trak,float pts,int flags){ 2207 2208 // printf("MOV track seek called %5.3f \n",pts); 2209 if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale; 2210 2211 if(trak->samplesize){ 2212 int sample=pts/trak->duration; 2213 // printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration); 2214 if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative 2215 trak->pos=0; 2216 while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos; 2217 if (trak->pos == trak->chunks_size) return -1; 2218 pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; 2219 } else { 2220 unsigned int ipts; 2221 if(!(flags&1)) pts+=trak->samples[trak->pos].pts; 2222 if(pts<0) pts=0; 2223 ipts=pts; 2224 //printf("MOV track seek - sample: %d \n",ipts); 2225 for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){ 2226 if(trak->samples[trak->pos].pts>=ipts) break; // found it! 2227 } 2228 if (trak->pos == trak->samples_size) return -1; 2229 if(trak->keyframes_size){ 2230 // find nearest keyframe 2231 int i; 2232 for(i=0;i<trak->keyframes_size;i++){ 2233 if(trak->keyframes[i]>=trak->pos) break; 1400 2234 } 1401 zret = inflate(&zstrm, Z_NO_FLUSH); 1402 if ((zret != Z_OK) && (zret != Z_STREAM_END)) 1403 { dprintf( "QT cmov inflate: ERR %d\n",zret); 1404 return; 1405 } 1406 #if 0 1407 else { 1408 FILE *DecOut; 1409 DecOut = fopen("Out.bin", "w"); 1410 fwrite(moov_buf, 1, moov_sz, DecOut); 1411 fclose(DecOut); 1412 } 1413 #endif 1414 if(moov_sz != zstrm.total_out) 1415 dprintf( "Warning! moov size differs cmov: %d zlib: %ld\n",moov_sz,zstrm.total_out); 1416 zret = inflateEnd(&zstrm); 1417 1418 backup=demuxer->stream; 1419 demuxer->stream=new_memory_stream(moov_buf,moov_sz); 1420 stream_skip(demuxer->stream,8); 1421 lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov' 1422 //free_stream(demuxer->stream); 1423 demuxer->stream=backup; 1424 free(cmov_buf); 1425 free(moov_buf); 1426 break; 1427 } 1428 #endif 1429 case MOV_FOURCC('u','d','t','a'): 1430 { 1431 unsigned int udta_id; 1432 off_t udta_len; 1433 off_t udta_size = len; 1434 1435 dprintf( "mov: user data record found\n"); 1436 dprintf( "Quicktime Clip Info:\n"); 1437 1438 while((len > 8) && (udta_size > 8)) 1439 { 1440 udta_len = stream_read_dword(demuxer->stream); 1441 udta_id = stream_read_dword(demuxer->stream); 1442 udta_size -= 8; 1443 dprintf( "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len); 1444 switch (udta_id) 1445 { 1446 case MOV_FOURCC(0xa9,'c','p','y'): 1447 case MOV_FOURCC(0xa9,'d','a','y'): 1448 case MOV_FOURCC(0xa9,'d','i','r'): 1449 /* 0xa9,'e','d','1' - '9' : edit timestamps */ 1450 case MOV_FOURCC(0xa9,'f','m','t'): 1451 case MOV_FOURCC(0xa9,'i','n','f'): 1452 case MOV_FOURCC(0xa9,'p','r','d'): 1453 case MOV_FOURCC(0xa9,'p','r','f'): 1454 case MOV_FOURCC(0xa9,'r','e','q'): 1455 case MOV_FOURCC(0xa9,'s','r','c'): 1456 case MOV_FOURCC('n','a','m','e'): 1457 case MOV_FOURCC(0xa9,'n','a','m'): 1458 case MOV_FOURCC(0xa9,'A','R','T'): 1459 case MOV_FOURCC(0xa9,'c','m','t'): 1460 case MOV_FOURCC(0xa9,'a','u','t'): 1461 case MOV_FOURCC(0xa9,'s','w','r'): 1462 { 1463 off_t text_len = stream_read_word(demuxer->stream); 1464 char text[text_len+2+1]; 1465 stream_read(demuxer->stream, (char *)&text, text_len+2); 1466 text[text_len+2] = 0x0; 1467 switch(udta_id) 1468 { 1469 case MOV_FOURCC(0xa9,'a','u','t'): 1470 demux_info_add(demuxer, "author", &text[2]); 1471 dprintf( " Author: %s\n", &text[2]); 1472 break; 1473 case MOV_FOURCC(0xa9,'c','p','y'): 1474 demux_info_add(demuxer, "copyright", &text[2]); 1475 dprintf( " Copyright: %s\n", &text[2]); 1476 break; 1477 case MOV_FOURCC(0xa9,'i','n','f'): 1478 dprintf( " Info: %s\n", &text[2]); 1479 break; 1480 case MOV_FOURCC('n','a','m','e'): 1481 case MOV_FOURCC(0xa9,'n','a','m'): 1482 demux_info_add(demuxer, "name", &text[2]); 1483 dprintf( " Name: %s\n", &text[2]); 1484 break; 1485 case MOV_FOURCC(0xa9,'A','R','T'): 1486 dprintf( " Artist: %s\n", &text[2]); 1487 break; 1488 case MOV_FOURCC(0xa9,'d','i','r'): 1489 dprintf( " Director: %s\n", &text[2]); 1490 break; 1491 case MOV_FOURCC(0xa9,'c','m','t'): 1492 demux_info_add(demuxer, "comments", &text[2]); 1493 dprintf( " Comment: %s\n", &text[2]); 1494 break; 1495 case MOV_FOURCC(0xa9,'r','e','q'): 1496 dprintf( " Requirements: %s\n", &text[2]); 1497 break; 1498 case MOV_FOURCC(0xa9,'s','w','r'): 1499 demux_info_add(demuxer, "encoder", &text[2]); 1500 dprintf( " Software: %s\n", &text[2]); 1501 break; 1502 case MOV_FOURCC(0xa9,'d','a','y'): 1503 dprintf( " Creation timestamp: %s\n", &text[2]); 1504 break; 1505 case MOV_FOURCC(0xa9,'f','m','t'): 1506 dprintf( " Format: %s\n", &text[2]); 1507 break; 1508 case MOV_FOURCC(0xa9,'p','r','d'): 1509 dprintf( " Producer: %s\n", &text[2]); 1510 break; 1511 case MOV_FOURCC(0xa9,'p','r','f'): 1512 dprintf( " Performer(s): %s\n", &text[2]); 1513 break; 1514 case MOV_FOURCC(0xa9,'s','r','c'): 1515 dprintf( " Source providers: %s\n", &text[2]); 1516 break; 1517 } 1518 udta_size -= 4+text_len; 1519 break; 1520 } 1521 /* some other shits: WLOC - window location, 1522 LOOP - looping style, 1523 SelO - play only selected frames 1524 AllF - play all frames 1525 */ 1526 case MOV_FOURCC('W','L','O','C'): 1527 case MOV_FOURCC('L','O','O','P'): 1528 case MOV_FOURCC('S','e','l','O'): 1529 case MOV_FOURCC('A','l','l','F'): 1530 default: 1531 { 1532 if( udta_len>udta_size) 1533 udta_len=udta_size; 1534 { 1535 char dump[udta_len-4]; 1536 stream_read(demuxer->stream, (char *)&dump, udta_len-4-4); 1537 udta_size -= udta_len; 1538 } 1539 } 1540 } 1541 } 1542 break; 1543 } /* eof udta */ 1544 default: 1545 id = be2me_32(id); 1546 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 1547 } /* endof switch */ 1548 } /* endof else */ 1549 1550 pos+=len+8; 1551 if(pos>=endpos) break; 1552 if(!stream_seek(demuxer->stream,pos)) break; 2235 if (i == trak->keyframes_size) return -1; 2236 if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1])) 2237 --i; 2238 trak->pos=trak->keyframes[i]; 2239 // printf("nearest keyframe: %d \n",trak->pos); 2240 } 2241 pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; 2242 } 2243 2244 // printf("MOV track seek done: %5.3f \n",pts); 2245 2246 return pts; 1553 2247 } 1554 } 1555 1556 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, 1557 off_t pos, off_t len, mov_track_t* trak) 1558 { 1559 switch(id) { 1560 case MOV_FOURCC('m','d','a','t'): { 1561 dprintf("Hmm, strange MOV, parsing mdat in lschunks?\n"); 1562 return -1; 2248 2249 static void demux_seek_mov(demuxer_t *demuxer,float pts,int flags){ 2250 mov_priv_t* priv=demuxer->priv; 2251 demux_stream_t* ds; 2252 mov_track_t* trak; 2253 2254 // printf("MOV seek called %5.3f flag=%d \n",pts,flags); 2255 2256 ds=demuxer->video; 2257 trak = stream_track(priv, ds); 2258 if (trak) { 2259 //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; 2260 //if(!(flags&1)) pts+=ds->pts; 2261 ds->pts=mov_seek_track(trak,pts,flags); 2262 if (ds->pts < 0) ds->eof = 1; 2263 else pts = ds->pts; 2264 flags=1; // absolute seconds 2265 } 2266 2267 ds=demuxer->audio; 2268 trak = stream_track(priv, ds); 2269 if (trak) { 2270 //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; 2271 //if(!(flags&1)) pts+=ds->pts; 2272 ds->pts=mov_seek_track(trak,pts,flags); 2273 if (ds->pts < 0) ds->eof = 1; 2274 if (demuxer->video->id < 0) 2275 ((sh_audio_t*)ds->sh)->delay = ds->pts; 2276 } 2277 1563 2278 } 1564 case MOV_FOURCC('f','r','e','e'): 1565 case MOV_FOURCC('u','d','t','a'): 1566 /* here not supported :p */ 1567 break; 1568 case MOV_FOURCC('t','k','h','d'): { 1569 dprintf("MOV: %*sTrack header!\n", level, ""); 1570 // read codec data 1571 trak->tkdata_len = len; 1572 trak->tkdata = malloc(trak->tkdata_len); 1573 stream_read(demuxer->stream, trak->tkdata, trak->tkdata_len); 1574 /* 1575 0 1 Version 1576 1 3 Flags 1577 4 4 Creation time 1578 8 4 Modification time 1579 12 4 Track ID 1580 16 4 Reserved 1581 20 4 Duration 1582 24 8 Reserved 1583 32 2 Layer 1584 34 2 Alternate group 1585 36 2 Volume 1586 38 2 Reserved 1587 40 36 Matrix structure 1588 76 4 Track width 1589 80 4 Track height 1590 */ 1591 dprintf( 1592 "tkhd len=%d ver=%d flags=0x%X id=%d dur=%d lay=%d vol=%d\n", 1593 trak->tkdata_len, trak->tkdata[0], trak->tkdata[1], 1594 char2int(trak->tkdata, 12), // id 1595 char2int(trak->tkdata, 20), // duration 1596 char2short(trak->tkdata, 32), // layer 1597 char2short(trak->tkdata, 36)); // volume 1598 break; 2279 2280 static int demux_mov_control(demuxer_t *demuxer, int cmd, void *arg){ 2281 mov_track_t* track; 2282 2283 // try the video track 2284 track = stream_track(demuxer->priv, demuxer->video); 2285 if (!track || !track->length) 2286 // otherwise try to get the info from the audio track 2287 track = stream_track(demuxer->priv, demuxer->audio); 2288 2289 if (!track || !track->length) 2290 return DEMUXER_CTRL_DONTKNOW; 2291 2292 switch(cmd) { 2293 case DEMUXER_CTRL_GET_TIME_LENGTH: 2294 if (!track->timescale) 2295 return DEMUXER_CTRL_DONTKNOW; 2296 *((double *)arg) = (double)track->length / track->timescale; 2297 return DEMUXER_CTRL_OK; 2298 2299 case DEMUXER_CTRL_GET_PERCENT_POS: 2300 { 2301 off_t pos = track->pos; 2302 if (track->durmap_size >= 1) 2303 pos *= track->durmap[0].dur; 2304 *((int *)arg) = (int)(100 * pos / track->length); 2305 return DEMUXER_CTRL_OK; 2306 } 2307 } 2308 return DEMUXER_CTRL_NOTIMPL; 1599 2309 } 1600 case MOV_FOURCC('m','d','h','d'): { 1601 dprintf( "MOV: %*sMedia header!\n", level, ""); 1602 int version = stream_read_char(demuxer->stream); 1603 stream_skip(demuxer->stream, (version == 1) ? 19 : 11); 1604 // read timescale 1605 trak->timescale = stream_read_dword(demuxer->stream); 1606 // read length 1607 if (version == 1) 1608 trak->length = stream_read_qword(demuxer->stream); 1609 else 1610 trak->length = stream_read_dword(demuxer->stream); 1611 break; 1612 } 1613 case MOV_FOURCC('h','d','l','r'): { 1614 unsigned int tmp = stream_read_dword(demuxer->stream); 1615 unsigned int type = stream_read_dword_le(demuxer->stream); 1616 unsigned int subtype = stream_read_dword_le(demuxer->stream); 1617 unsigned int manufact = stream_read_dword_le(demuxer->stream); 1618 unsigned int comp_flags = stream_read_dword(demuxer->stream); 1619 unsigned int comp_mask = stream_read_dword(demuxer->stream); 1620 int len = stream_read_char(demuxer->stream); 1621 char* str = malloc(len + 1); 1622 stream_read(demuxer->stream, str, len); 1623 str[len] = 0; 1624 dprintf( 1625 "MOV: %*sHandler header: %.4s/%.4s (%.4s) %s\n", level, "", 1626 (char *)&type, (char *)&subtype, (char *)&manufact, str); 1627 free(str); 1628 switch(bswap_32(type)) { 1629 case MOV_FOURCC('m','h','l','r'): 1630 trak->media_handler = bswap_32(subtype); 1631 break; 1632 case MOV_FOURCC('d','h','l','r'): 1633 trak->data_handler = bswap_32(subtype); 1634 break; 1635 default: 1636 dprintf( 1637 "MOV: unknown handler class: 0x%X (%.4s)\n", 1638 bswap_32(type), (char *)&type); 1639 } 1640 break; 1641 } 1642 case MOV_FOURCC('v','m','h','d'): { 1643 dprintf( "MOV: %*sVideo header!\n", level, ""); 1644 trak->type = MOV_TRAK_VIDEO; 1645 // read video data 1646 break; 1647 } 1648 case MOV_FOURCC('s','m','h','d'): { 1649 dprintf( "MOV: %*sSound header!\n", level, ""); 1650 trak->type = MOV_TRAK_AUDIO; 1651 // read audio data 1652 break; 1653 } 1654 case MOV_FOURCC('g','m','h','d'): { 1655 dprintf( "MOV: %*sGeneric header!\n", level, ""); 1656 trak->type = MOV_TRAK_GENERIC; 1657 break; 1658 } 1659 case MOV_FOURCC('n','m','h','d'): { 1660 dprintf( "MOV: %*sGeneric header!\n", level, ""); 1661 trak->type = MOV_TRAK_GENERIC; 1662 break; 1663 } 1664 case MOV_FOURCC('s','t','s','d'): { 1665 int i = stream_read_dword(demuxer->stream); // temp! 1666 int count = stream_read_dword(demuxer->stream); 1667 dprintf( "MOV: %*sDescription list! (cnt:%d)\n", 1668 level, "", count); 1669 for (i = 0; i < count; i++) { 1670 off_t pos = stream_tell(demuxer->stream); 1671 off_t len = stream_read_dword(demuxer->stream); 1672 unsigned int fourcc = stream_read_dword_le(demuxer->stream); 1673 /* some files created with Broadcast 2000 (e.g. ilacetest.mov) 1674 contain raw I420 video but have a yv12 fourcc */ 1675 if (fourcc == mmioFOURCC('y','v','1','2')) 1676 fourcc = mmioFOURCC('I','4','2','0'); 1677 if (len < 8) 1678 break; // error 1679 dprintf( 1680 "MOV: %*s desc #%d: %.4s (%"PRId64" bytes)\n", level, "", 1681 i, (char *)&fourcc, (int64_t)len - 16); 1682 if (fourcc != trak->fourcc && i) 1683 dprintf("MOW: warning - different fourcc\n"); 1684 // if(!i) 1685 { 1686 trak->fourcc = fourcc; 1687 // read type specific (audio/video/time/text etc) header 1688 // NOTE: trak type is not yet known at this point :((( 1689 trak->stdata_len = len - 8; 1690 trak->stdata = malloc(trak->stdata_len); 1691 stream_read(demuxer->stream, trak->stdata, trak->stdata_len); 1692 } 1693 if (!stream_seek(demuxer->stream, pos + len)) 1694 break; 1695 } 1696 break; 1697 } 1698 case MOV_FOURCC('s','t','t','s'): { 1699 int temp = stream_read_dword(demuxer->stream); 1700 int len = stream_read_dword(demuxer->stream); 1701 int i; 1702 unsigned int pts = 0; 1703 dprintf( 1704 "MOV: %*sSample duration table! (%d blocks)\n", level, "", 1705 len); 1706 trak->durmap = calloc(len, sizeof(mov_durmap_t)); 1707 trak->durmap_size = len; 1708 for (i = 0; i < len; i++) { 1709 trak->durmap[i].num = stream_read_dword(demuxer->stream); 1710 trak->durmap[i].dur = stream_read_dword(demuxer->stream); 1711 pts += trak->durmap[i].num * trak->durmap[i].dur; 1712 } 1713 if (trak->length != pts) 1714 dprintf( "Warning! pts=%d length=%d\n", 1715 pts, trak->length); 1716 break; 1717 } 1718 case MOV_FOURCC('s','t','s','c'): { 1719 int temp = stream_read_dword(demuxer->stream); 1720 int len = stream_read_dword(demuxer->stream); 1721 int ver = (temp << 24); 1722 int flags = (temp << 16) | (temp << 8) | temp; 1723 int i; 1724 dprintf( 1725 "MOV: %*sSample->Chunk mapping table! (%d blocks) (ver:%d,flags:%d)\n", level, "", 1726 len, ver, flags); 1727 // read data: 1728 trak->chunkmap_size = len; 1729 trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t)); 1730 for (i = 0; i < len; i++) { 1731 trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1; 1732 trak->chunkmap[i].spc = stream_read_dword(demuxer->stream); 1733 trak->chunkmap[i].sdid = stream_read_dword(demuxer->stream); 1734 } 1735 break; 1736 } 1737 case MOV_FOURCC('s','t','s','z'): { 1738 int temp = stream_read_dword(demuxer->stream); 1739 int ss=stream_read_dword(demuxer->stream); 1740 int ver = (temp << 24); 1741 int flags = (temp << 16) | (temp << 8) | temp; 1742 int entries = stream_read_dword(demuxer->stream); 1743 int i; 1744 dprintf( 1745 "MOV: %*sSample size table! (entries=%d ss=%d) (ver:%d,flags:%d)\n", level, "", 1746 entries, ss, ver, flags); 1747 trak->samplesize = ss; 1748 if (!ss) { 1749 // variable samplesize 1750 trak->samples = realloc_struct(trak->samples, entries, sizeof(mov_sample_t)); 1751 trak->samples_size = entries; 1752 for (i = 0; i < entries; i++) 1753 trak->samples[i].size = stream_read_dword(demuxer->stream); 1754 } 1755 break; 1756 } 1757 case MOV_FOURCC('s','t','c','o'): { 1758 int temp = stream_read_dword(demuxer->stream); 1759 int len = stream_read_dword(demuxer->stream); 1760 int i; 1761 dprintf( 1762 "MOV: %*sChunk offset table! (%d chunks)\n", level, "", 1763 len); 1764 // extend array if needed: 1765 if (len > trak->chunks_size) { 1766 trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t)); 1767 trak->chunks_size = len; 1768 } 1769 // read elements: 1770 for(i = 0; i < len; i++) 1771 trak->chunks[i].pos = stream_read_dword(demuxer->stream); 1772 break; 1773 } 1774 case MOV_FOURCC('c','o','6','4'): { 1775 int temp = stream_read_dword(demuxer->stream); 1776 int len = stream_read_dword(demuxer->stream); 1777 int i; 1778 dprintf( 1779 "MOV: %*s64bit chunk offset table! (%d chunks)\n", level, "", 1780 len); 1781 // extend array if needed: 1782 if (len > trak->chunks_size) { 1783 trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t)); 1784 trak->chunks_size = len; 1785 } 1786 // read elements: 1787 for (i = 0; i < len; i++) { 1788 #ifndef _LARGEFILE_SOURCE 1789 if (stream_read_dword(demuxer->stream) != 0) 1790 dprintf( "Chunk %d has got 64bit address, but you've MPlayer compiled without LARGEFILE support!\n", i); 1791 trak->chunks[i].pos = stream_read_dword(demuxer->stream); 1792 #else 1793 trak->chunks[i].pos = stream_read_qword(demuxer->stream); 1794 #endif 1795 } 1796 break; 1797 } 1798 case MOV_FOURCC('s','t','s','s'): { 1799 int temp = stream_read_dword(demuxer->stream); 1800 int entries = stream_read_dword(demuxer->stream); 1801 int ver = (temp << 24); 1802 int flags = (temp << 16) | (temp<<8) | temp; 1803 int i; 1804 dprintf( 1805 "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "", 1806 entries, ver, flags); 1807 trak->keyframes_size = entries; 1808 trak->keyframes = calloc(entries, sizeof(unsigned int)); 1809 for (i = 0; i < entries; i++) 1810 trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1; 1811 break; 1812 } 1813 case MOV_FOURCC('m','d','i','a'): { 1814 dprintf( "MOV: %*sMedia stream!\n", level, ""); 1815 lschunks(demuxer, level + 1, pos + len, trak); 1816 break; 1817 } 1818 case MOV_FOURCC('m','i','n','f'): { 1819 dprintf( "MOV: %*sMedia info!\n", level, ""); 1820 lschunks(demuxer, level + 1 ,pos + len, trak); 1821 break; 1822 } 1823 case MOV_FOURCC('s','t','b','l'): { 1824 dprintf( "MOV: %*sSample info!\n", level, ""); 1825 lschunks(demuxer, level + 1, pos + len, trak); 1826 break; 1827 } 1828 case MOV_FOURCC('e','d','t','s'): { 1829 dprintf( "MOV: %*sEdit atom!\n", level, ""); 1830 lschunks(demuxer, level + 1, pos + len, trak); 1831 break; 1832 } 1833 case MOV_FOURCC('e','l','s','t'): { 1834 int temp = stream_read_dword(demuxer->stream); 1835 int entries = stream_read_dword(demuxer->stream); 1836 int ver = (temp << 24); 1837 int flags = (temp << 16) | (temp << 8) | temp; 1838 int i; 1839 dprintf( 1840 "MOV: %*sEdit list table (%d entries) (ver:%d,flags:%d)\n", level, "", 1841 entries, ver, flags); 1842 #if 1 1843 trak->editlist_size = entries; 1844 trak->editlist = calloc(trak->editlist_size, sizeof(mov_editlist_t)); 1845 for (i = 0; i < entries; i++) { 1846 int dur = stream_read_dword(demuxer->stream); 1847 int mt = stream_read_dword(demuxer->stream); 1848 int mr = stream_read_dword(demuxer->stream); // 16.16fp 1849 trak->editlist[i].dur = dur; 1850 trak->editlist[i].pos = mt; 1851 trak->editlist[i].speed = mr; 1852 dprintf( 1853 "MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n", level, "", 1854 i, dur, mt, (float)mr/65536.0f); 1855 } 1856 #endif 1857 break; 1858 } 1859 case MOV_FOURCC('c','o','d','e'): { 1860 /* XXX: Implement atom 'code' for FLASH support */ 1861 break; 1862 } 1863 default: 1864 id = be2me_32(id); 1865 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len); 1866 break; 1867 }//switch(id) 1868 return 0; 1869 } 1870 1871 static demuxer_t* mov_read_header(demuxer_t* demuxer){ 1872 mov_priv_t* priv=demuxer->priv; 1873 int t_no; 1874 int best_a_id=-1, best_a_len=0; 1875 int best_v_id=-1, best_v_len=0; 1876 1877 dprintf( "mov_read_header!\n"); 1878 1879 // Parse header: 1880 stream_reset(demuxer->stream); 1881 if(!stream_seek(demuxer->stream,priv->moov_start)) 1882 { 1883 dprintf("MOV: Cannot seek to the beginning of the Movie header (0x%"PRIx64")\n", 1884 (int64_t)priv->moov_start); 1885 return 0; 1886 } 1887 lschunks(demuxer, 0, priv->moov_end, NULL); 1888 // just in case we have hit eof while parsing... 1889 demuxer->stream->eof = 0; 1890 // dprintf( "--------------\n"); 1891 1892 // find the best (longest) streams: 1893 for(t_no=0;t_no<priv->track_db;t_no++){ 1894 mov_track_t* trak=priv->tracks[t_no]; 1895 int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size; 1896 if(demuxer->a_streams[t_no]){ // need audio 1897 if(len>best_a_len){ best_a_len=len; best_a_id=t_no; } 1898 } 1899 if(demuxer->v_streams[t_no]){ // need video 1900 if(len>best_v_len){ best_v_len=len; best_v_id=t_no; } 1901 } 1902 } 1903 dprintf( "MOV: longest streams: A: #%d (%d samples) V: #%d (%d samples)\n", 1904 best_a_id,best_a_len,best_v_id,best_v_len); 1905 if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id; 1906 if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id; 1907 1908 // setup sh pointers: 1909 if(demuxer->audio->id>=0){ 1910 sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id]; 1911 if(sh){ 1912 demuxer->audio->sh=sh; sh->ds=demuxer->audio; 1913 } else { 1914 dprintf( "MOV: selected audio stream (%d) does not exists\n",demuxer->audio->id); 1915 demuxer->audio->id=-2; 1916 } 1917 } 1918 if(demuxer->video->id>=0){ 1919 sh_video_t* sh=demuxer->v_streams[demuxer->video->id]; 1920 if(sh){ 1921 demuxer->video->sh=sh; sh->ds=demuxer->video; 1922 } else { 1923 dprintf( "MOV: selected video stream (%d) does not exists\n",demuxer->video->id); 1924 demuxer->video->id=-2; 1925 } 1926 } 1927 1928 if(demuxer->video->id<0 && demuxer->audio->id<0) { 1929 /* No AV streams found. Try to find an MPEG stream. */ 1930 for(t_no=0;t_no<priv->track_db;t_no++){ 1931 mov_track_t* trak=priv->tracks[t_no]; 1932 if(trak->media_handler == MOV_FOURCC('M','P','E','G')) { 1933 stream_t *s; 1934 demuxer_t *od; 1935 1936 demuxer->video->id = t_no; 1937 s = new_ds_stream(demuxer->video); 1938 od = demux_open(s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL); 1939 if(od) return new_demuxers_demuxer(od, od, od); 1940 demuxer->video->id = -2; //new linked demuxer couldn't be allocated 1941 break; 1942 } 1943 } 1944 } 1945 1946 #if 0 1947 if( mp_msg_test(MSGL_DBG3) ){ 1948 for(t_no=0;t_no<priv->track_db;t_no++){ 1949 mov_track_t* trak=priv->tracks[t_no]; 1950 if(trak->type==MOV_TRAK_GENERIC){ 1951 int i; 1952 int fd; 1953 char name[20]; 1954 dprintf( "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size); 1955 for (i=0; i<trak->samples_size; i++) 1956 { 1957 int len=trak->samples[i].size; 1958 char buf[len]; 1959 stream_seek(demuxer->stream, trak->samples[i].pos); 1960 snprintf(name, 20, "t%02d-s%03d.%s", t_no,i, 1961 (trak->media_handler==MOV_FOURCC('f','l','s','h')) ? 1962 "swf":"dump"); 1963 fd = open(name, O_CREAT|O_WRONLY); 1964 // { int j; 1965 // for(j=0;j<trak->stdata_len-3; j++) 1966 // printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b')); 1967 // } 1968 if( //trak->media_handler==MOV_FOURCC('s','p','r','t') && 1969 trak->stdata_len>=16 && 1970 char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b') 1971 ){ 1972 int newlen=stream_read_dword(demuxer->stream); 1973 #ifdef HAVE_ZLIB 1974 // unzip: 1975 z_stream zstrm; 1976 int zret; 1977 char buf2[newlen]; 1978 1979 len-=4; 1980 stream_read(demuxer->stream, buf, len); 1981 1982 zstrm.zalloc = (alloc_func)0; 1983 zstrm.zfree = (free_func)0; 1984 zstrm.opaque = (voidpf)0; 1985 zstrm.next_in = buf; 1986 zstrm.avail_in = len; 1987 zstrm.next_out = buf2; 1988 zstrm.avail_out = newlen; 1989 1990 zret = inflateInit(&zstrm); 1991 zret = inflate(&zstrm, Z_NO_FLUSH); 1992 if(newlen != zstrm.total_out) 1993 dprintf( "Warning! unzipped frame size differs hdr: %d zlib: %ld\n",newlen,zstrm.total_out); 1994 1995 write(fd, buf2, newlen); 1996 } else { 1997 #else 1998 len-=4; 1999 dprintf( "******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen); 2000 } 2001 { 2002 #endif 2003 stream_read(demuxer->stream, buf, len); 2004 write(fd, buf, len); 2005 } 2006 close(fd); 2007 } 2008 } 2009 } 2010 } 2011 demuxer->stream->eof = 0; 2012 #endif 2013 2014 return demuxer; 2015 } 2016 2017 /** 2018 * \brief return the mov track that belongs to a demuxer stream 2019 * \param ds the demuxer stream, may be NULL 2020 * \return the mov track info structure belonging to the stream, 2021 * NULL if not found 2022 */ 2023 static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) { 2024 if (ds && (ds->id >= 0) && (ds->id < priv->track_db)) 2025 return priv->tracks[ds->id]; 2026 return NULL; 2027 } 2028 2029 // return value: 2030 // 0 = EOF or no stream found 2031 // 1 = successfully read a packet 2032 static int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){ 2033 mov_priv_t* priv=demuxer->priv; 2034 mov_track_t* trak=NULL; 2035 float pts; 2036 int x; 2037 off_t pos; 2038 2039 if (ds->eof) return 0; 2040 trak = stream_track(priv, ds); 2041 if (!trak) return 0; 2042 2043 if(trak->samplesize){ 2044 // read chunk: 2045 if(trak->pos>=trak->chunks_size) return 0; // EOF 2046 stream_seek(demuxer->stream,trak->chunks[trak->pos].pos); 2047 pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; 2048 if(trak->samplesize!=1) 2049 { 2050 dprintf( "WARNING! Samplesize(%d) != 1\n", 2051 trak->samplesize); 2052 if((trak->fourcc != MOV_FOURCC('t','w','o','s')) && (trak->fourcc != MOV_FOURCC('s','o','w','t'))) 2053 x=trak->chunks[trak->pos].size*trak->samplesize; 2054 else 2055 x=trak->chunks[trak->pos].size; 2056 } 2057 x=trak->chunks[trak->pos].size; 2058 // printf("X = %d\n", x); 2059 /* the following stuff is audio related */ 2060 if (trak->type == MOV_TRAK_AUDIO){ 2061 if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){ 2062 // stsd version 1 - we have audio compression ratio info: 2063 x/=char2int(trak->stdata,28); // samples/packet 2064 // x*=char2int(trak->stdata,32); // bytes/packet 2065 x*=char2int(trak->stdata,36); // bytes/frame 2066 } else { 2067 if(ds->ss_div && ds->ss_mul){ 2068 // workaround for buggy files like 7up-high-traffic-areas.mov, 2069 // with missing stsd v1 header containing compression rate 2070 x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix ! HACK ! 2071 } else { 2072 x*=trak->nchannels; 2073 x*=trak->samplebytes; 2074 } 2075 } 2076 dprintf( "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts); 2077 } /* MOV_TRAK_AUDIO */ 2078 pos=trak->chunks[trak->pos].pos; 2079 } else { 2080 int frame=trak->pos; 2081 // editlist support: 2082 if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){ 2083 // find the right editlist entry: 2084 if(frame<trak->editlist[trak->editlist_pos].start_frame) 2085 trak->editlist_pos=0; 2086 while(trak->editlist_pos<trak->editlist_size-1 && 2087 frame>=trak->editlist[trak->editlist_pos+1].start_frame) 2088 ++trak->editlist_pos; 2089 if(frame>=trak->editlist[trak->editlist_pos].start_frame+ 2090 trak->editlist[trak->editlist_pos].frames) return 0; // EOF 2091 // calc real frame index: 2092 frame-=trak->editlist[trak->editlist_pos].start_frame; 2093 frame+=trak->editlist[trak->editlist_pos].start_sample; 2094 // calc pts: 2095 pts=(float)(trak->samples[frame].pts+ 2096 trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale; 2097 } else { 2098 if(frame>=trak->samples_size) return 0; // EOF 2099 pts=(float)trak->samples[frame].pts/(float)trak->timescale; 2100 } 2101 // read sample: 2102 stream_seek(demuxer->stream,trak->samples[frame].pos); 2103 x=trak->samples[frame].size; 2104 pos=trak->samples[frame].pos; 2105 } 2106 if(trak->pos==0 && trak->stream_header_len>0){ 2107 // we have to append the stream header... 2108 demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len); 2109 memcpy(dp->buffer,trak->stream_header,trak->stream_header_len); 2110 stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x); 2111 free(trak->stream_header); 2112 trak->stream_header = NULL; 2113 trak->stream_header_len = 0; 2114 dp->pts=pts; 2115 dp->flags=0; 2116 dp->pos=pos; // FIXME? 2117 ds_add_packet(ds,dp); 2118 } else 2119 ds_read_packet(ds,demuxer->stream,x,pts,pos,0); 2120 2121 ++trak->pos; 2122 2123 return 1; 2124 2125 } 2126 2127 static float mov_seek_track(mov_track_t* trak,float pts,int flags){ 2128 2129 // printf("MOV track seek called %5.3f \n",pts); 2130 if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale; 2131 2132 if(trak->samplesize){ 2133 int sample=pts/trak->duration; 2134 // printf("MOV track seek - chunk: %d (pts: %5.3f dur=%d) \n",sample,pts,trak->duration); 2135 if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative 2136 trak->pos=0; 2137 while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos; 2138 if (trak->pos == trak->chunks_size) return -1; 2139 pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale; 2140 } else { 2141 unsigned int ipts; 2142 if(!(flags&1)) pts+=trak->samples[trak->pos].pts; 2143 if(pts<0) pts=0; 2144 ipts=pts; 2145 //printf("MOV track seek - sample: %d \n",ipts); 2146 for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){ 2147 if(trak->samples[trak->pos].pts>=ipts) break; // found it! 2148 } 2149 if (trak->pos == trak->samples_size) return -1; 2150 if(trak->keyframes_size){ 2151 // find nearest keyframe 2152 int i; 2153 for(i=0;i<trak->keyframes_size;i++){ 2154 if(trak->keyframes[i]>=trak->pos) break; 2155 } 2156 if (i == trak->keyframes_size) return -1; 2157 if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1])) 2158 --i; 2159 trak->pos=trak->keyframes[i]; 2160 // printf("nearest keyframe: %d \n",trak->pos); 2161 } 2162 pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; 2163 } 2164 2165 // printf("MOV track seek done: %5.3f \n",pts); 2166 2167 return pts; 2168 } 2169 2170 static void demux_seek_mov(demuxer_t *demuxer,float pts,int flags){ 2171 mov_priv_t* priv=demuxer->priv; 2172 demux_stream_t* ds; 2173 mov_track_t* trak; 2174 2175 // printf("MOV seek called %5.3f flag=%d \n",pts,flags); 2176 2177 ds=demuxer->video; 2178 trak = stream_track(priv, ds); 2179 if (trak) { 2180 //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; 2181 //if(!(flags&1)) pts+=ds->pts; 2182 ds->pts=mov_seek_track(trak,pts,flags); 2183 if (ds->pts < 0) ds->eof = 1; 2184 else pts = ds->pts; 2185 flags=1; // absolute seconds 2186 } 2187 2188 ds=demuxer->audio; 2189 trak = stream_track(priv, ds); 2190 if (trak) { 2191 //if(flags&2) pts*=(float)trak->length/(float)trak->timescale; 2192 //if(!(flags&1)) pts+=ds->pts; 2193 ds->pts=mov_seek_track(trak,pts,flags); 2194 if (ds->pts < 0) ds->eof = 1; 2195 if (demuxer->video->id < 0) 2196 ((sh_audio_t*)ds->sh)->delay = ds->pts; 2197 } 2198 2199 } 2200 2201 static int demux_mov_control(demuxer_t *demuxer, int cmd, void *arg){ 2202 mov_track_t* track; 2203 2204 // try the video track 2205 track = stream_track(demuxer->priv, demuxer->video); 2206 if (!track || !track->length) 2207 // otherwise try to get the info from the audio track 2208 track = stream_track(demuxer->priv, demuxer->audio); 2209 2210 if (!track || !track->length) 2211 return DEMUXER_CTRL_DONTKNOW; 2212 2213 switch(cmd) { 2214 case DEMUXER_CTRL_GET_TIME_LENGTH: 2215 if (!track->timescale) 2216 return DEMUXER_CTRL_DONTKNOW; 2217 *((double *)arg) = (double)track->length / track->timescale; 2218 return DEMUXER_CTRL_OK; 2219 2220 case DEMUXER_CTRL_GET_PERCENT_POS: 2221 { 2222 off_t pos = track->pos; 2223 if (track->durmap_size >= 1) 2224 pos *= track->durmap[0].dur; 2225 *((int *)arg) = (int)(100 * pos / track->length); 2226 return DEMUXER_CTRL_OK; 2227 } 2228 } 2229 return DEMUXER_CTRL_NOTIMPL; 2230 } 2231 2232 2233 demuxer_desc_t demuxer_desc_mov = { 2234 "Quicktime/MP4 demuxer", 2235 "mov", 2236 "Quicktime/MOV", 2237 "Arpi, Al3x, Atmos, others", 2238 "Handles Quicktime, MP4, 3GP", 2239 DEMUXER_TYPE_MOV, 2240 0, // slow autodetect 2241 mov_check_file, 2242 demux_mov_fill_buffer, 2243 mov_read_header, 2244 demux_close_mov, 2245 demux_seek_mov, 2246 demux_mov_control 2247 }; 2310 2311 2312 demuxer_desc_t demuxer_desc_mov = { 2313 "Quicktime/MP4 demuxer", 2314 "mov", 2315 "Quicktime/MOV", 2316 "Arpi, Al3x, Atmos, others", 2317 "Handles Quicktime, MP4, 3GP", 2318 DEMUXER_TYPE_MOV, 2319 1, // slow autodetect 2320 mov_check_file, 2321 demux_mov_fill_buffer, 2322 mov_read_header, 2323 demux_close_mov, 2324 demux_seek_mov, 2325 demux_mov_control 2326 };
Note:
See TracChangeset
for help on using the changeset viewer.