comparison libmpdemux/demux_mov.c @ 24182:8d6ad131c010

Split lschunks function further, it is simply too huge to do any useful changes (e.g. for more proper support for multi-codec tracks).
author reimar
date Sat, 25 Aug 2007 18:09:00 +0000
parents fd31150fe5b8
children 7e5e6eff5a4f
comparison
equal deleted inserted replaced
24181:fe3fd951b8cc 24182:8d6ad131c010
576 } 576 }
577 577
578 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id, 578 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
579 off_t pos, off_t len, mov_track_t* trak); 579 off_t pos, off_t len, mov_track_t* trak);
580 580
581 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ 581 static int gen_sh_audio(sh_audio_t* sh, mov_track_t* trak, int timescale) {
582 mov_priv_t* priv=demuxer->priv;
583 // printf("lschunks (level=%d,endpos=%x)\n", level, endpos);
584 while(1){
585 off_t pos;
586 off_t len;
587 unsigned int id;
588 //
589 pos=stream_tell(demuxer->stream);
590 // printf("stream_tell==%d\n",pos);
591 if(pos>=endpos) return; // END
592 len=stream_read_dword(demuxer->stream);
593 // printf("len==%d\n",len);
594 if(len<8) return; // error
595 len-=8;
596 id=stream_read_dword(demuxer->stream);
597 //
598 mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",(char *)&id,(int)len);
599 //
600 if(trak){
601 if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0)
602 return;
603 } else { /* not in track */
604 switch(id) {
605 case MOV_FOURCC('m','v','h','d'): {
606 int version = stream_read_char(demuxer->stream);
607 stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
608 priv->timescale=stream_read_dword(demuxer->stream);
609 if (version == 1)
610 priv->duration=stream_read_qword(demuxer->stream);
611 else
612 priv->duration=stream_read_dword(demuxer->stream);
613 mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len,
614 (int)priv->timescale,(int)priv->duration);
615 break;
616 }
617 case MOV_FOURCC('t','r','a','k'): {
618 // if(trak) printf("MOV: Warning! trak in trak?\n");
619 if(priv->track_db>=MOV_MAX_TRACKS){
620 mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk);
621 return;
622 }
623 if(!priv->track_db) mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n");
624 trak=malloc(sizeof(mov_track_t));
625 memset(trak,0,sizeof(mov_track_t));
626 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db);
627 trak->id=priv->track_db;
628 priv->tracks[priv->track_db]=trak;
629 lschunks(demuxer,level+1,pos+len,trak);
630 mov_build_index(trak,priv->timescale);
631 switch(trak->type){
632 case MOV_TRAK_AUDIO: {
633 #if 0 582 #if 0
634 struct { 583 struct {
635 int16_t version; // 0 or 1 (version 1 is qt3.0+) 584 int16_t version; // 0 or 1 (version 1 is qt3.0+)
636 int16_t revision; // 0 585 int16_t revision; // 0
637 int32_t vendor_id; // 0 586 int32_t vendor_id; // 0
655 // ([int32_t size,int32_t type,some data ],repeat) 604 // ([int32_t size,int32_t type,some data ],repeat)
656 } my_stdata; 605 } my_stdata;
657 #endif 606 #endif
658 int version, adjust; 607 int version, adjust;
659 int is_vorbis = 0; 608 int is_vorbis = 0;
660 sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db);
661 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "mov", priv->track_db);
662 sh->format=trak->fourcc; 609 sh->format=trak->fourcc;
663 610
664 // crude audio delay from editlist0 hack ::atm 611 // crude audio delay from editlist0 hack ::atm
665 if(trak->editlist_size>=1) { 612 if(trak->editlist_size>=1) {
666 if(trak->editlist[0].pos == -1) { 613 if(trak->editlist[0].pos == -1) {
667 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 614 sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale;
668 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay); 615 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay);
669 } 616 }
670 } 617 }
671 618
672 619
972 // if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){ 919 // if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){
973 // // (auto)selected audio track: 920 // // (auto)selected audio track:
974 // demuxer->audio->id=priv->track_db; 921 // demuxer->audio->id=priv->track_db;
975 // demuxer->audio->sh=sh; sh->ds=demuxer->audio; 922 // demuxer->audio->sh=sh; sh->ds=demuxer->audio;
976 // } 923 // }
977 break; 924 return 1;
978 } 925 }
979 case MOV_TRAK_VIDEO: { 926
927 static int gen_sh_video(sh_video_t* sh, mov_track_t* trak, int timescale) {
980 int depth, i, entry; 928 int depth, i, entry;
981 int flag, start, count_flag, end, palette_count, gray; 929 int flag, start, count_flag, end, palette_count, gray;
982 int hdr_ptr = 76; // the byte just after depth 930 int hdr_ptr = 76; // the byte just after depth
983 unsigned char *palette_map; 931 unsigned char *palette_map;
984 sh_video_t* sh=new_sh_video(demuxer,priv->track_db);
985 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "mov", priv->track_db);
986 sh->format=trak->fourcc; 932 sh->format=trak->fourcc;
987 933
988 // crude video delay from editlist0 hack ::atm 934 // crude video delay from editlist0 hack ::atm
989 if(trak->editlist_size>=1) { 935 if(trak->editlist_size>=1) {
990 if(trak->editlist[0].pos == -1) { 936 if(trak->editlist[0].pos == -1) {
991 sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale; 937 sh->stream_delay = (float)trak->editlist[0].dur/(float)timescale;
992 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay); 938 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay);
993 } 939 }
994 } 940 }
995 941
996 942
997 if (trak->stdata_len < 78) { 943 if (trak->stdata_len < 78) {
998 mp_msg(MSGT_DEMUXER, MSGL_WARN, 944 mp_msg(MSGT_DEMUXER, MSGL_WARN,
999 "MOV: Invalid (%d bytes instead of >= 78) video trak desc\n", 945 "MOV: Invalid (%d bytes instead of >= 78) video trak desc\n",
1000 trak->stdata_len); 946 trak->stdata_len);
1001 break; 947 return 0;
1002 } 948 }
1003 depth = trak->stdata[75] | (trak->stdata[74] << 8); 949 depth = trak->stdata[75] | (trak->stdata[74] << 8);
1004 // stdata[]: 950 // stdata[]:
1005 // 8 short version 951 // 8 short version
1006 // 10 short revision 952 // 10 short revision
1302 // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){ 1248 // if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){
1303 // // (auto)selected video track: 1249 // // (auto)selected video track:
1304 // demuxer->video->id=priv->track_db; 1250 // demuxer->video->id=priv->track_db;
1305 // demuxer->video->sh=sh; sh->ds=demuxer->video; 1251 // demuxer->video->sh=sh; sh->ds=demuxer->video;
1306 // } 1252 // }
1253 return 1;
1254 }
1255
1256 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){
1257 mov_priv_t* priv=demuxer->priv;
1258 // printf("lschunks (level=%d,endpos=%x)\n", level, endpos);
1259 while(1){
1260 off_t pos;
1261 off_t len;
1262 unsigned int id;
1263 //
1264 pos=stream_tell(demuxer->stream);
1265 // printf("stream_tell==%d\n",pos);
1266 if(pos>=endpos) return; // END
1267 len=stream_read_dword(demuxer->stream);
1268 // printf("len==%d\n",len);
1269 if(len<8) return; // error
1270 len-=8;
1271 id=stream_read_dword(demuxer->stream);
1272 //
1273 mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",(char *)&id,(int)len);
1274 //
1275 if(trak){
1276 if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0)
1277 return;
1278 } else { /* not in track */
1279 switch(id) {
1280 case MOV_FOURCC('m','v','h','d'): {
1281 int version = stream_read_char(demuxer->stream);
1282 stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
1283 priv->timescale=stream_read_dword(demuxer->stream);
1284 if (version == 1)
1285 priv->duration=stream_read_qword(demuxer->stream);
1286 else
1287 priv->duration=stream_read_dword(demuxer->stream);
1288 mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sMovie header (%d bytes): tscale=%d dur=%d\n",level,"",(int)len,
1289 (int)priv->timescale,(int)priv->duration);
1290 break;
1291 }
1292 case MOV_FOURCC('t','r','a','k'): {
1293 // if(trak) printf("MOV: Warning! trak in trak?\n");
1294 if(priv->track_db>=MOV_MAX_TRACKS){
1295 mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk);
1296 return;
1297 }
1298 if(!priv->track_db) mp_msg(MSGT_DEMUX, MSGL_V, "--------------\n");
1299 trak=malloc(sizeof(mov_track_t));
1300 memset(trak,0,sizeof(mov_track_t));
1301 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db);
1302 trak->id=priv->track_db;
1303 priv->tracks[priv->track_db]=trak;
1304 lschunks(demuxer,level+1,pos+len,trak);
1305 mov_build_index(trak,priv->timescale);
1306 switch(trak->type){
1307 case MOV_TRAK_AUDIO: {
1308 sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db);
1309 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "mov", priv->track_db);
1310 gen_sh_audio(sh, trak, priv->timescale);
1311 break;
1312 }
1313 case MOV_TRAK_VIDEO: {
1314 sh_video_t* sh=new_sh_video(demuxer,priv->track_db);
1315 mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "mov", priv->track_db);
1316 gen_sh_video(sh, trak, priv->timescale);
1307 break; 1317 break;
1308 } 1318 }
1309 case MOV_TRAK_GENERIC: 1319 case MOV_TRAK_GENERIC:
1310 if (trak->fourcc == mmioFOURCC('m','p','4','s') || 1320 if (trak->fourcc == mmioFOURCC('m','p','4','s') ||
1311 trak->fourcc == mmioFOURCC('t','x','3','g') || 1321 trak->fourcc == mmioFOURCC('t','x','3','g') ||