Mercurial > mplayer.hg
annotate demux_mov.c @ 2051:596653943fa1
tired
author | gabucino |
---|---|
date | Tue, 02 Oct 2001 21:59:43 +0000 |
parents | 5216f108cb4f |
children | 6f6eb4f8e7a0 |
rev | line source |
---|---|
1490 | 1 // QuickTime MOV file parser |
2 // based on TOOLS/movinfo.c by A'rpi & Al3x | |
3 | |
4 #include <stdio.h> | |
5 #include <stdlib.h> | |
6 #include <unistd.h> | |
7 | |
1567 | 8 #include "config.h" |
9 #include "mp_msg.h" | |
1973
5216f108cb4f
all error/warn/info messages moved to help_mp-en.h for translation
arpi
parents:
1567
diff
changeset
|
10 #include "help_mp.h" |
1490 | 11 |
12 #include "stream.h" | |
13 #include "demuxer.h" | |
14 | |
15 #include "wine/mmreg.h" | |
16 #include "wine/avifmt.h" | |
17 #include "wine/vfw.h" | |
18 | |
19 #include "codec-cfg.h" | |
20 #include "stheader.h" | |
21 | |
22 typedef struct { | |
23 int id; | |
24 int type; | |
25 int timescale; | |
26 int width,height; // for video | |
27 unsigned int fourcc; | |
28 int data_len; | |
29 unsigned char* data; | |
30 } mov_track_t; | |
31 | |
32 #define MOV_MAX_TRACKS 256 | |
33 | |
34 #define MOV_TRAK_UNKNOWN 0 | |
35 #define MOV_TRAK_VIDEO 1 | |
36 #define MOV_TRAK_AUDIO 2 | |
37 | |
38 typedef struct { | |
39 off_t moov_start; | |
40 off_t moov_end; | |
41 off_t mdat_start; | |
42 off_t mdat_end; | |
43 int track_db; | |
44 mov_track_t* tracks[MOV_MAX_TRACKS]; | |
45 } mov_priv_t; | |
46 | |
47 #define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d)) | |
48 | |
49 int mov_check_file(demuxer_t* demuxer){ | |
50 int flags=0; | |
51 mov_priv_t* priv=malloc(sizeof(mov_priv_t)); | |
52 | |
1567 | 53 mp_msg(MSGT_DEMUX,MSGL_V,"Checking for MOV\n"); |
1490 | 54 |
55 memset(priv,0,sizeof(mov_priv_t)); | |
56 demuxer->priv=priv; | |
57 | |
58 while(1){ | |
59 off_t len=stream_read_dword(demuxer->stream); | |
60 unsigned int id=stream_read_dword(demuxer->stream); | |
61 if(stream_eof(demuxer->stream)) break; // EOF | |
62 if(len<8) break; // invalid chunk | |
63 switch(id){ | |
64 case MOV_FOURCC('m','o','o','v'): | |
1567 | 65 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie header found!\n"); |
1490 | 66 priv->moov_start=stream_tell(demuxer->stream); |
67 priv->moov_end=priv->moov_start+len-8; | |
68 flags|=1; | |
69 break; | |
70 case MOV_FOURCC('m','d','a','t'): | |
1567 | 71 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Movie DATA found!\n"); |
1490 | 72 priv->mdat_start=stream_tell(demuxer->stream); |
73 priv->mdat_end=priv->mdat_start+len-8; | |
74 flags|=2; | |
75 break; | |
76 default: | |
1567 | 77 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: unknown chunk: %.4s %d\n",&id,(int)len); |
1490 | 78 } |
79 if(!stream_skip(demuxer->stream,len-8)) break; | |
80 } | |
81 | |
82 return (flags==3); | |
83 } | |
84 | |
85 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){ | |
86 mov_priv_t* priv=demuxer->priv; | |
87 while(1){ | |
88 off_t pos; | |
89 off_t len; | |
90 unsigned int id; | |
91 // | |
92 pos=stream_tell(demuxer->stream); | |
93 if(pos>=endpos) return; // END | |
94 len=stream_read_dword(demuxer->stream); | |
95 if(len<8) return; // error | |
96 len-=8; | |
97 id=stream_read_dword(demuxer->stream); | |
98 // | |
1567 | 99 mp_msg(MSGT_DEMUX,MSGL_DBG2,"lschunks %.4s %d\n",&id,(int)len); |
1490 | 100 // |
101 if(trak){ | |
102 switch(id){ | |
103 case MOV_FOURCC('t','k','h','d'): { | |
1567 | 104 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sTrack header!\n",level,""); |
1490 | 105 // read width x height |
106 break; | |
107 } | |
108 case MOV_FOURCC('m','d','h','d'): { | |
1567 | 109 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia header!\n",level,""); |
1490 | 110 // read timescale |
111 break; | |
112 } | |
113 case MOV_FOURCC('v','m','h','d'): { | |
1567 | 114 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sVideo header!\n",level,""); |
1490 | 115 trak->type=MOV_TRAK_VIDEO; |
116 // read video data | |
117 break; | |
118 } | |
119 case MOV_FOURCC('s','m','h','d'): { | |
1567 | 120 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSound header!\n",level,""); |
1490 | 121 trak->type=MOV_TRAK_AUDIO; |
122 // read audio data | |
123 break; | |
124 } | |
125 case MOV_FOURCC('s','t','s','d'): { | |
126 int i=stream_read_dword(demuxer->stream); // temp! | |
127 int count=stream_read_dword(demuxer->stream); | |
1567 | 128 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sDescription list! (cnt:%d)\n",level,"",count); |
1490 | 129 for(i=0;i<count;i++){ |
130 off_t pos=stream_tell(demuxer->stream); | |
131 off_t len=stream_read_dword(demuxer->stream); | |
132 unsigned int fourcc=stream_read_dword_le(demuxer->stream); | |
133 if(len<8) break; // error | |
1567 | 134 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*s desc #%d: %.4s",level,"",i,&fourcc); |
1490 | 135 if(!i){ |
136 trak->fourcc=fourcc; | |
137 // read codec data | |
138 trak->data_len=len-8; | |
139 trak->data=malloc(trak->data_len); | |
140 stream_read(demuxer->stream,trak->data,trak->data_len); | |
141 if(trak->type==MOV_TRAK_VIDEO && trak->data_len>43){ | |
1567 | 142 mp_msg(MSGT_DEMUX,MSGL_V," '%.*s'",trak->data_len-43,trak->data+43); |
1490 | 143 } |
144 } | |
1567 | 145 mp_msg(MSGT_DEMUX,MSGL_V,"\n"); |
1490 | 146 if(fourcc!=trak->fourcc && i) |
1973
5216f108cb4f
all error/warn/info messages moved to help_mp-en.h for translation
arpi
parents:
1567
diff
changeset
|
147 mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVvariableFourCC); |
1490 | 148 if(!stream_seek(demuxer->stream,pos+len)) break; |
149 } | |
150 break; | |
151 } | |
152 case MOV_FOURCC('m','d','i','a'): { | |
1567 | 153 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia stream!\n",level,""); |
1490 | 154 lschunks(demuxer,level+1,pos+len,trak); |
155 break; | |
156 } | |
157 case MOV_FOURCC('m','i','n','f'): { | |
1567 | 158 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sMedia info!\n",level,""); |
1490 | 159 lschunks(demuxer,level+1,pos+len,trak); |
160 break; | |
161 } | |
162 case MOV_FOURCC('s','t','b','l'): { | |
1567 | 163 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: %*sSample info!\n",level,""); |
1490 | 164 lschunks(demuxer,level+1,pos+len,trak); |
165 break; | |
166 } | |
167 }//switch(id) | |
168 } else | |
169 if(id==MOV_FOURCC('t','r','a','k')){ | |
170 // if(trak) printf("MOV: Warning! trak in trak?\n"); | |
171 if(priv->track_db>=MOV_MAX_TRACKS){ | |
1973
5216f108cb4f
all error/warn/info messages moved to help_mp-en.h for translation
arpi
parents:
1567
diff
changeset
|
172 mp_msg(MSGT_DEMUX,MSGL_WARN,MSGTR_MOVtooManyTrk); |
1490 | 173 return; |
174 } | |
175 trak=malloc(sizeof(mov_track_t)); | |
176 memset(trak,0,sizeof(mov_track_t)); | |
1567 | 177 mp_msg(MSGT_DEMUX,MSGL_V,"MOV: Track #%d:\n",priv->track_db); |
1490 | 178 trak->id=priv->track_db; |
179 priv->tracks[priv->track_db++]=trak; | |
180 lschunks(demuxer,level+1,pos+len,trak); | |
181 trak=NULL; | |
182 } else | |
183 if(id==MOV_FOURCC('c','m','o','v')){ | |
1973
5216f108cb4f
all error/warn/info messages moved to help_mp-en.h for translation
arpi
parents:
1567
diff
changeset
|
184 mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVcomprhdr); |
1490 | 185 return; |
186 } | |
187 | |
188 pos+=len+8; | |
189 if(pos>=endpos) break; | |
190 if(!stream_seek(demuxer->stream,pos)) break; | |
191 } | |
192 } | |
193 | |
194 int mov_read_header(demuxer_t* demuxer){ | |
195 mov_priv_t* priv=demuxer->priv; | |
196 | |
197 // printf("mov_read_header!\n"); | |
198 | |
199 // Parse header: | |
200 if(!stream_seek(demuxer->stream,priv->moov_start)) return 0; // ??? | |
201 lschunks(demuxer, 0, priv->moov_end, NULL); | |
202 | |
203 // Build tables: | |
204 // ... | |
205 | |
1973
5216f108cb4f
all error/warn/info messages moved to help_mp-en.h for translation
arpi
parents:
1567
diff
changeset
|
206 mp_msg(MSGT_DEMUX,MSGL_ERR,MSGTR_MOVnotyetsupp); |
1490 | 207 |
208 return 1; | |
209 } |