1 
2 /*
3  * xa_qt.c
4  *
5  * Copyright (C) 1993-1998,1999 by Mark Podlipec.
6  * All rights reserved.
7  *
8  * This software may be freely used, copied and redistributed without
9  * fee for non-commerical purposes provided that this copyright
10  * notice is preserved intact on all copies.
11  *
12  * There is no warranty or other guarantee of fitness of this software.
13  * It is provided solely "as is". The author disclaims all
14  * responsibility and liability with respect to this software's usage
15  * or its effect upon hardware or computer systems.
16  *
17  */
18 /* REVISIONS ***********
19  * 31Aug94  RPZA was using *iptr+=row_inc instead of iptr+=row_inc.
20  * 15Sep94  Added support for RAW32 format. straight RGB with 0x00 up front.
21  * 19Sep94  Fixed stereo audio bug. Needed to double bps with stereo snd.
22  * 20Sep94  I forgot to declare xin in the QT_Read_Audio_STSD(xin) and
23  *	    that caused problems on the Alpha machines.
24  * 20Sep94  Added RAW4,RAW16,RAW24,RAW32,Gray CVID and Gray Other codecs.
25  * 07Nov94  Fixed bug in RLE,RLE16,RLE24,RLE32 and RLE1 code, where I
26  *          had improperly guessed what a header meant. Now it's a different
27  *	    hopeful more correct guess.
28  * 29Dec94  Above bug wasn't fixe in RLE(8bit), now it is.
29  * 30Jan95  Appletalk on SONY uses directory .afprsrc for resource forks
30  *	    instead of .resource like other programs use.
31  *	    patch written by Kazushi Yoshida.
32  * 11Feb95  Fixed Bug with RLE depth 1 codec.
33  * 04Mar95  Added Dithering(+F option) to Cinepak Video Codec.
34  * 08Mar95  Fixed audio Bug with SGI generated quicktimes audio depth > 8.
35  * 17Mar95  Fixed bug that was causing quicktime to erroneously send
36  *          back a FULL_IM flag allowing serious skipping to occur. This
37  *          causes on screen corruption if the Video Codec doesn't
38  *          really support serious skipping.
39  * 11Apr95  Fixed bug in QT_Create_Gray_Cmap that caused last color of
40  *	    colormap not to be generated correctly. Only affected
41  *	    the Gray Quicktime codecs.
42  * 16Jun95  Removed Cinepak Codec per Radius request.
43  * 15Sep95  Code snippet to support erroneous Quicktime files that
44  *	    have the length of the "mdat" atom, but not the "mdat" ID.
45  * 15Sep95  Better check for truncated Quicktime files
46  * 26Feb96  Fixed prob in Read_Video_Data, where timing chunks were
47  *          incremented properly resulting in video/audio sync problems.
48  *  1Mar96  Moved Video Codecs into xa_qt_decs.c file
49  * 19Mar96  Modified for support of audio only files.
50  */
51 #include "xa_qt.h"
52 #include "xa_codecs.h"
53 #include <sys/stat.h>
54 
55 #ifdef XA_ZLIB
56 #include <zlib.h>
57 #endif
58 
59 static XA_CODEC_HDR qt_codec_hdr;
60 
61 extern xaULONG QT_Video_Codec_Query();
62 extern xaULONG XA_Mem_Open_Init();
63 
64 xaULONG QT_Read_Video_Codec_HDR();
65 xaULONG QT_Read_Audio_Codec_HDR();
66 void QT_Audio_Type();
67 xaULONG QT_Read_File();
68 
69 
70 void QT_Create_Default_Cmap();
71 void QT_Create_Gray_Cmap();
72 extern char *XA_rindex();
73 
74 void CMAP_Cache_Clear();
75 void CMAP_Cache_Init();
76 
77 
78 xaUSHORT qt_gamma_adj[32];
79 
80 QTV_CODEC_HDR *qtv_codecs;
81 QTS_CODEC_HDR *qts_codecs;
82 xaULONG qtv_codec_num,qts_codec_num;
83 
84 extern XA_ACTION *ACT_Get_Action();
85 extern XA_CHDR *ACT_Get_CMAP();
86 extern XA_CHDR *CMAP_Create_332();
87 extern XA_CHDR *CMAP_Create_422();
88 extern XA_CHDR *CMAP_Create_Gray();
89 extern void ACT_Add_CHDR_To_Action();
90 extern void ACT_Setup_Mapped();
91 extern XA_CHDR *CMAP_Create_CHDR_From_True();
92 extern xaUBYTE *UTIL_RGB_To_FS_Map();
93 extern xaUBYTE *UTIL_RGB_To_Map();
94 extern xaULONG CMAP_Find_Closest();
95 extern XA_ANIM_SETUP *XA_Get_Anim_Setup();
96 extern void XA_Free_Anim_Setup();
97 extern void ACT_Setup_Delta();
98 
99 
100 #ifdef TEMPORARILY_REMOVE
101 FILE *QT_Open_File();
102 xaULONG QT_Parse_Bin();
103 #endif
104 xaULONG QT_Parse_Chunks();
105 xaULONG QT_Read_Video_Data();
106 xaULONG QT_Read_Audio_Data();
107 
108 void QT_Print_ID();
109 void QT_Read_MVHD();
110 void QT_Read_TKHD();
111 void QT_Read_ELST();
112 void QT_Read_MDHD();
113 void QT_Read_HDLR();
114 xaULONG QT_Read_Video_STSD();
115 void QT_Read_Audio_STSD();
116 void QT_Read_Name();
117 void QT_Read_STTS();
118 void QT_Read_STSS();
119 void QT_Read_STCO();
120 void QT_Read_STSZ();
121 void QT_Read_STSC();
122 void QT_Read_STGS();
123 void QT_Free_Stuff();
124 void QT_Codec_List();
125 
126 
127 
128 QT_MVHDR qt_mvhdr;
129 QT_TKHDR qt_tkhdr;
130 QT_MDHDR qt_mdhdr;
131 QT_HDLR_HDR qt_hdlr_hdr;
132 
133 #ifdef TEMPORARILY_REMOVED
134 char qt_rfilename[256];
135 char qt_dfilename[256];
136 #endif
137 static xaULONG qt_video_flag, qt_audio_flag;
138 static xaULONG qt_data_flag;
139 static xaULONG qt_v_flag, qt_s_flag;
140 static xaULONG qt_moov_flag;
141 
142 static xaULONG qt_frame_cnt;
143 static xaULONG qt_mv_timescale,qt_md_timescale;
144 static xaULONG qt_vid_timescale, qt_aud_timescale;
145 static xaULONG qt_tk_timescale,qts_tk_timescale,qtv_tk_timescale;
146 
147 #define QT_CODEC_UNK   0x000
148 
149 /*** SOUND SUPPORT ****/
150 static xaULONG qt_audio_attempt;
151 static xaULONG qt_audio_type;
152 static xaULONG qt_audio_freq;
153 static xaULONG qt_audio_chans;
154 static xaULONG qt_audio_bps;
155 static xaULONG qt_audio_end;
156 xaULONG XA_Add_Sound();
157 
158 
159 QT_FRAME *qt_frame_start,*qt_frame_cur;
160 
QT_Add_Frame(time,timelo,act)161 QT_FRAME *QT_Add_Frame(time,timelo,act)
162 xaULONG time,timelo;
163 XA_ACTION *act;
164 {
165   QT_FRAME *fframe;
166 
167   fframe = (QT_FRAME *) malloc(sizeof(QT_FRAME));
168   if (fframe == 0) TheEnd1("QT_Add_Frame: malloc err");
169 
170   fframe->time = time;
171   fframe->timelo = timelo;
172   fframe->act = act;
173   fframe->next = 0;
174 
175   if (qt_frame_start == 0) qt_frame_start = fframe;
176   else qt_frame_cur->next = fframe;
177 
178   qt_frame_cur = fframe;
179   qt_frame_cnt++;
180   return(fframe);
181 }
182 
QT_Free_Frame_List(fframes)183 void QT_Free_Frame_List(fframes)
184 QT_FRAME *fframes;
185 {
186   QT_FRAME *ftmp;
187   while(fframes != 0)
188   {
189     ftmp = fframes;
190     fframes = fframes->next;
191     FREE(ftmp,0x9000);
192   }
193 }
194 
195 
Is_QT_File(filename)196 xaLONG Is_QT_File(filename)
197 char *filename;
198 {
199 #ifdef TEMPORARILY_REMOVED
200   ZILE *Zin;
201   xaULONG ret;
202   if ( (Zin=QT_Open_File(filename,qt_rfilename,qt_dfilename)) == 0)
203 				return(xaNOFILE);
204   ret = QT_Parse_Bin(Zin);
205   fclose(Zin);
206   if ( ret != 0 ) return(xaTRUE);
207 #endif
208   return(xaFALSE);
209 }
210 
211 /* FOR PARSING Quicktime Files */
212 xaULONG *qtv_samp_sizes,*qts_samp_sizes;
213 xaULONG qtv_samp_num,qts_samp_num;
214 xaULONG qt_init_duration,qts_init_duration, qtv_init_duration;
215 xaULONG qt_start_offset,qts_start_offset, qtv_start_offset;
216 
217 QT_S2CHUNK_HDR *qtv_s2chunks,*qts_s2chunks;
218 xaULONG qtv_s2chunk_num,qts_s2chunk_num;
219 
220 QT_T2SAMP_HDR *qtv_t2samps,*qts_t2samps;
221 xaULONG qtv_t2samp_num,qts_t2samp_num;
222 
223 xaULONG qtv_chunkoff_num,qts_chunkoff_num;
224 xaULONG *qtv_chunkoffs,*qts_chunkoffs;
225 
226 xaULONG qtv_codec_lstnum,qts_codec_lstnum;
227 xaULONG qtv_chunkoff_lstnum,qts_chunkoff_lstnum;
228 xaULONG qtv_samp_lstnum,qts_samp_lstnum;
229 xaULONG qtv_s2chunk_lstnum,qts_s2chunk_lstnum;
230 xaULONG qt_stgs_num;
231 
232 xaULONG qt_has_ctab;
233 
234 xaULONG qt_saw_audio, qt_saw_video;
235 
236 /* main() */
QT_Read_File(fname,anim_hdr,audio_attempt)237 xaULONG QT_Read_File(fname,anim_hdr,audio_attempt)
238 char *fname;
239 XA_ANIM_HDR *anim_hdr;
240 xaULONG audio_attempt;  /* xaTRUE is audio is to be attempted */
241 { XA_INPUT *xin;
242   xaLONG i,t_time;
243   xaULONG t_timelo;
244   XA_ANIM_SETUP *qt;
245   xaULONG qt_has_audio, qt_has_video;
246 
247   xin = anim_hdr->xin;
248   qt = XA_Get_Anim_Setup();
249   qt->vid_time 		= XA_GET_TIME( 100 ); /* default 10 fps */
250   qt->compression	= QT_CODEC_UNK;
251 
252 
253   qt_saw_audio	= xaFALSE;
254   qt_saw_video	= xaFALSE;
255   qt_has_audio	= xaFALSE;
256   qt_has_video	= xaFALSE;
257   qt_has_ctab	= xaFALSE;
258   qt_stgs_num	= 0;
259   qtv_codec_lstnum	= qts_codec_lstnum = 0;
260   qtv_chunkoff_lstnum	= qts_chunkoff_lstnum = 0;
261   qtv_samp_lstnum	= qts_samp_lstnum = 0;
262   qtv_codecs = 0;
263   qts_codecs = 0;
264   qtv_codec_num 	= qts_codec_num = 0;
265   qt_data_flag = xaFALSE;
266   qt_video_flag		= 0;
267   qt_audio_flag		= 0;
268   qt_v_flag		= qt_s_flag = 0;
269   qt_moov_flag = xaFALSE;
270 
271   qt_frame_cnt = 0;
272   qt_frame_start = 0;
273   qt_frame_cur = 0;
274 
275   qt_vid_timescale	= qt_aud_timescale = 1000;
276   qt_mv_timescale	= qt_md_timescale = 1000;
277   qts_tk_timescale 	= qtv_tk_timescale 	= 1000;
278   qtv_chunkoff_num	= qts_chunkoff_num = 0;
279   qtv_chunkoffs		= qts_chunkoffs = 0;
280   qtv_s2chunk_num	= qts_s2chunk_lstnum = 0;
281   qtv_s2chunks		= qts_s2chunks = 0;
282   qtv_s2chunk_num	= qts_s2chunk_lstnum = 0;
283   qtv_t2samp_num	= qts_t2samp_num = 0;
284   qtv_t2samps		= qts_t2samps = 0;
285   qtv_samp_sizes	= qts_samp_sizes = 0;
286   qtv_samp_num		= qts_samp_num = 0;
287   qt_init_duration	= qts_init_duration	= qtv_init_duration = 0;
288   qt_start_offset 	= qts_start_offset	= qtv_start_offset = 0;
289 
290   qt_audio_attempt	= audio_attempt;
291 
292   for(i=0;i<32;i++) qt_gamma_adj[i] = xa_gamma_adj[ ((i<<3)|(i>>2)) ];
293 
294 #ifdef TEMPORARILY_REMOVED
295   if ( (xin=QT_Open_File(fname,qt_rfilename,qt_dfilename)) == 0)
296   {
297     fprintf(stdout,"QT_Read: can't open %s\n",qt_rfilename);
298     XA_Free_Anim_Setup(qt);
299     return(xaFALSE);
300   }
301 
302   if ( QT_Parse_Bin(xin) == 0 )
303   {
304     fprintf(stdout,"Not quicktime file\n");
305     XA_Free_Anim_Setup(qt);
306     return(xaFALSE);
307   }
308 #endif
309 
310   if (QT_Parse_Chunks(anim_hdr,qt,xin) == xaFALSE)
311   {
312     QT_Free_Stuff();
313     XA_Free_Anim_Setup(qt);
314     return(xaFALSE);
315   }
316 
317   if (qt_data_flag == xaFALSE)
318   {
319     fprintf(stderr,"QT: no data found in file\n");
320     xin->Close_File(xin);
321     return(xaFALSE);
322   }
323 #ifdef TEMPORARILY_REMOVED
324   if (qt_data_flag == xaFALSE)
325   { /* mdat was not in .rscr file need to open .data file */
326     fclose(xin); /* close .rscr file */
327     if (qt_dfilename[0] == 0)
328     { fprintf(stdout,"QT_Data: No data in %s file and no *.data file.\n",
329 		qt_rfilename);
330       fprintf(stdout,"         Some Quicktimes do not contain info playable by XAnim.\n");
331       return(xaFALSE);
332     }
333     if ( (xin=fopen(qt_dfilename,XA_OPEN_MODE)) == 0)
334     { fprintf(stdout,"QT_Data: can't open %s file.\n",qt_dfilename);
335       return(xaFALSE);
336     }
337   } else strcpy(qt_dfilename,qt_rfilename); /* r file is d file */
338 #endif
339 
340 DEBUG_LEVEL1 fprintf(stdout,"reading data\n");
341 
342   if (qtv_samp_sizes && qt_video_flag)
343 		qt_has_video = QT_Read_Video_Data(qt,xin,anim_hdr);
344   if (qts_samp_sizes && qt_audio_flag && (qt_audio_attempt==xaTRUE))
345 		qt_has_audio = QT_Read_Audio_Data(qt,xin,anim_hdr);
346   xin->Close_File(xin);
347 
348   if ((qt_has_video == xaFALSE) || (qt_frame_cnt == 0))
349   {
350 
351     if (qt_has_audio == xaFALSE)  /* no video and no audio */
352     {
353 
354       if ((qt_saw_video == xaTRUE) && (qt_saw_audio == xaTRUE))
355       { fprintf(stdout,
356 	   "  Notice: Video and Audio are present, but not yet supported.\n");
357       }
358       else if ((qt_saw_video == xaTRUE) && (qt_saw_audio == xaFALSE))
359       { fprintf(stdout,
360 	   "  Notice: Video is present, but not yet supported.\n");
361       }
362       else if ((qt_saw_video == xaFALSE) && (qt_saw_audio == xaTRUE))
363       { fprintf(stdout,
364 	   "  Notice: Audio is present, but not yet supported.\n");
365       }
366       else
367       {		 /* At least we saw the moov header */
368         if (qt_moov_flag == xaTRUE)
369 	{
370 		/* No Video and we weren't trying for audio */
371           if (qt_audio_attempt == xaFALSE)
372           {
373              fprintf(stdout,"QT: no video to play. possibly truncated.\n");
374           }
375           else
376 	  {
377 		/* No Video and No Audio */
378 	    fprintf(stdout,"QT: no video/audio to play. possibly truncated.\n");
379 	  }
380         }
381         else  /* either truncated or missing .rsrc file */
382 	{
383 	  fprintf(stdout,
384 		"QT: file possibly truncated or missing .rsrc info.\n");
385         }
386       }
387       return(xaFALSE);
388     }
389 
390     if (qt_saw_video == xaTRUE)
391     { fprintf(stdout,
392 	   "  Notice: Video is present, but not yet supported.\n");
393     }
394 
395 /* NO LONGER???
396     if (qtv_samp_sizes)
397 	fprintf(stdout,"QT Notice: No supported Video frames - treating as audio only file\n");
398 */
399 
400     anim_hdr->total_time = (qt_mvhdr.duration * 1000) / (qt_mvhdr.timescale);
401   }
402   else
403   {
404     anim_hdr->frame_lst = (XA_FRAME *)
405                                 malloc( sizeof(XA_FRAME) * (qt_frame_cnt+1));
406     if (anim_hdr->frame_lst == NULL) TheEnd1("QT_Read_File: frame malloc err");
407 
408     qt_frame_cur = qt_frame_start;
409     i = 0;
410     t_time = 0;
411     t_timelo = 0;
412     while(qt_frame_cur != 0)
413     { if (i >= qt_frame_cnt)
414       { fprintf(stdout,"QT_Read_Anim: frame inconsistency %d %d\n",
415                 i,qt_frame_cnt); break;
416       }
417       anim_hdr->frame_lst[i].time_dur = qt_frame_cur->time;
418       anim_hdr->frame_lst[i].zztime = t_time;
419       t_time	+= qt_frame_cur->time;
420       t_timelo	+= qt_frame_cur->timelo;
421       while(t_timelo >= (1<<24)) {t_time++; t_timelo -= (1<<24);}
422       anim_hdr->frame_lst[i].act = qt_frame_cur->act;
423       qt_frame_cur = qt_frame_cur->next;
424       i++;
425     }
426     if (i > 0)
427     { anim_hdr->last_frame = i - 1;
428       anim_hdr->total_time = anim_hdr->frame_lst[i-1].zztime
429                                 + anim_hdr->frame_lst[i-1].time_dur;
430     }
431     else { anim_hdr->last_frame = 0; anim_hdr->total_time = 0; }
432 
433     if (xa_verbose)
434     { fprintf(stdout, "  Frame Stats: Size=%dx%d  Frames=%d",
435 				qt->imagex,qt->imagey,qt_frame_cnt);
436       if (anim_hdr->total_time)
437       { float fps = (float)(1000 * qt_frame_cnt)/(float)(anim_hdr->total_time);
438         fprintf(stdout, "  avfps=%2.1f\n",fps);
439       }
440       else fprintf(stdout,"\n");
441     }
442     anim_hdr->imagex = qt->max_imagex;
443     anim_hdr->imagey = qt->max_imagey;
444     anim_hdr->imagec = qt->imagec;
445     anim_hdr->imaged = 8; /* nop */
446     anim_hdr->frame_lst[i].time_dur = 0;
447     anim_hdr->frame_lst[i].zztime = -1;
448     anim_hdr->frame_lst[i].act  = 0;
449     anim_hdr->loop_frame = 0;
450   }
451 
452   if (xa_buffer_flag == xaFALSE) anim_hdr->anim_flags |= ANIM_SNG_BUF;
453   anim_hdr->max_fvid_size = qt->max_fvid_size;
454   anim_hdr->max_faud_size = qt->max_faud_size;
455 	/***----------------------------------------------------------***
456 	 * If reading from file, then use the data fork file name
457 	 * as the file name.
458 	 ***----------------------------------------------------------***/
459   if (xa_file_flag == xaTRUE)
460   { /* xaULONG len; */
461     anim_hdr->anim_flags |= ANIM_USE_FILE;
462 #ifdef TEMPORARILY_REMOVED
463     len = strlen(qt_dfilename) + 1;
464     anim_hdr->fname = (char *)malloc(len);
465     if (anim_hdr->fname==0) TheEnd1("QT: malloc fname err");
466     strcpy(anim_hdr->fname,qt_dfilename);
467 #endif
468   }
469   anim_hdr->fname = anim_hdr->name;
470   QT_Free_Stuff();
471   XA_Free_Anim_Setup(qt);
472   return(xaTRUE);
473 }
474 
QT_Free_Stuff()475 void QT_Free_Stuff()
476 {
477   QT_Free_Frame_List(qt_frame_start);
478   if (qtv_samp_sizes) FREE(qtv_samp_sizes,0x9003);
479   if (qts_samp_sizes) FREE(qts_samp_sizes,0x9004);
480   if (qtv_codecs) FREE(qtv_codecs,0x9005);
481   if (qts_codecs) FREE(qts_codecs,0x9006);
482   if (qtv_t2samps) FREE(qtv_t2samps,0x9007);
483   if (qts_t2samps) FREE(qts_t2samps,0x9008);
484   if (qtv_s2chunks) FREE(qtv_s2chunks,0x9009);
485   if (qts_s2chunks) FREE(qts_s2chunks,0x900a);
486   if (qtv_chunkoffs) FREE(qtv_chunkoffs,0x900b);
487   if (qts_chunkoffs) FREE(qts_chunkoffs,0x900c);
488 }
489 
490 /****------------------------------------------------------------------****
491  * Quicktime exists natively on Macintosh as a .rsrc file(containing
492  * all the headers) and a .data file(containing all the vid/aud/txt/etc data)
493  *
494  * Hopefully the file was flattened, made into single fork, saved for
495  * export, etc, before being send into the real world.  In this case
496  * all the info needed is contained in one single file.
497  *
498  * However, all the fun is in the other convoluted solutions developed
499  * to cross-platform the Macintosh .rsrc/.data forks to unix.
500  *
501  * If sent across using MacBinary and unpacked with macutils.
502  *
503  *    filename.data		data fork
504  *    filename.rsrc		rsrc fork
505  *
506  * Sony's NEWS-OS when file sharing over AppleTalk does the following:
507  *    filename			data fork
508  *    .afprsrc/filename		rsrc fork
509  *
510  * Another file sharing method is:
511  *    filename			data fork
512  *    .resource/filename	rsrc fork
513  *
514  *
515  * This routine determines the rsrc file name and the data file name.
516  ****------------------------------------------------------------------****/
517 
QT_Parse_Chunks(anim_hdr,qt,xin)518 xaULONG QT_Parse_Chunks(anim_hdr,qt,xin)
519 XA_ANIM_HDR *anim_hdr;
520 XA_ANIM_SETUP *qt;
521 XA_INPUT *xin;
522 {
523   xaLONG file_len;
524   xaULONG id,len;
525 
526   file_len = 1;
527   while(file_len > 0)
528   {
529     len = xin->Read_MSB_U32(xin);
530     id  = xin->Read_MSB_U32(xin);
531 
532 /* if (xa_verbose) */
533 DEBUG_LEVEL1
534 	fprintf(stdout,"%c%c%c%c %04x len = %x file_len =  %x\n",
535 	(char)(id >> 24),(char)((id>>16)&0xff),
536 	(char)((id>>8)&0xff),(char)(id&0xff),id,len,file_len);
537 
538     if ( (len == 0) && (id == QT_mdat) )
539     {
540       fprintf(stdout,"QT: mdat len is 0. You also need a .rsrc file.\n");
541       return(xaFALSE);
542     }
543     if (len < 8) { file_len = 0; continue; } /* just bad - xinish this */
544     if (file_len == 1)
545     {
546       if (id == QT_moov) file_len = len;
547       else file_len = len;
548     }
549 
550 /* if (xa_verbose) */
551 DEBUG_LEVEL1
552     fprintf(stdout,"  len = %x file_len = %x\n",len,file_len);
553 
554     switch(id)
555     {
556     /*--------------ATOMS------------------*/
557       case QT_trak:
558 	qt_v_flag = qt_s_flag = 0;
559 	qtv_codec_lstnum = qtv_codec_num;
560 	qts_codec_lstnum = qts_codec_num;
561 	qtv_chunkoff_lstnum = qtv_chunkoff_num;
562 	qts_chunkoff_lstnum = qts_chunkoff_num;
563 	qtv_samp_lstnum = qtv_samp_num;
564 	qts_samp_lstnum = qts_samp_num;
565 	qtv_s2chunk_lstnum = qtv_s2chunk_num;
566 	qts_s2chunk_lstnum = qts_s2chunk_num;
567 	file_len -= 8;
568 	break;
569       case QT_moov:
570         qt_moov_flag = xaTRUE;
571 	file_len -= 8;
572 	break;
573       case QT_mdia:
574       case QT_minf:
575       case QT_stbl:
576       case QT_edts:
577 	file_len -= 8;
578 	break;
579     /*---------------STUFF------------------*/
580       case QT_mvhd:
581 	QT_Read_MVHD(xin,&qt_mvhdr);
582 	file_len -= len;
583 	break;
584       case QT_tkhd:
585 	QT_Read_TKHD(xin,&qt_tkhdr);
586 	file_len -= len;
587 	break;
588       case QT_elst:
589 	QT_Read_ELST(xin,&qt_start_offset,&qt_init_duration);
590 	file_len -= len;
591 	break;
592       case QT_mdhd:
593 	QT_Read_MDHD(xin,&qt_mdhdr);
594 	file_len -= len;
595 	break;
596       case QT_hdlr:
597 	QT_Read_HDLR(xin,len,&qt_hdlr_hdr);
598 	file_len -= len;
599 	break;
600     /*--------------DATA CHUNKS-------------*/
601       case QT_mdat:  /* data is included in .rsrc - assumed flatness */
602 	xin->Seek_FPos(xin,(len-8),1); /* skip over it for now */
603 	file_len -= len;
604 	qt_data_flag = xaTRUE;
605 	break;
606       case QT_stsd:
607 	if (qt_v_flag)
608 	{ qt_saw_video = xaTRUE;
609 	  QT_Read_Video_STSD(anim_hdr,qt,xin,(len-8));
610 	}
611 	else if (qt_s_flag)
612 	{ qt_saw_audio = xaTRUE;
613 	  QT_Read_Audio_STSD(xin,(len-8));
614 	}
615         else xin->Seek_FPos(xin,(len-8),1);
616 	file_len -= len;
617 	break;
618       case QT_stts:
619 	if (qt_v_flag)
620 		QT_Read_STTS(xin,(len-8),&qtv_t2samp_num,&qtv_t2samps);
621 /*POD NOTE: AUDIO doesn't need? probably, just haven't been bit by it yet.
622 	else if (qt_s_flag)
623 		QT_Read_STTS(xin,(len-8),&qts_t2samp_num,&qts_t2samps);
624 */
625         else	xin->Seek_FPos(xin,(len-8),1);
626 	file_len -= len;
627 	break;
628       case QT_stss:
629 	QT_Read_STSS(xin);
630 	file_len -= len;
631 	break;
632       case QT_stco:
633 	if (qt_v_flag) QT_Read_STCO(xin,&qtv_chunkoff_num,&qtv_chunkoffs);
634 	else if (qt_s_flag) QT_Read_STCO(xin,&qts_chunkoff_num,&qts_chunkoffs);
635 	else xin->Seek_FPos(xin,(len-8),1);
636 	file_len -= len;
637 	break;
638       case QT_stsz:
639 	if (qt_v_flag) QT_Read_STSZ(xin,len,&qtv_samp_num,&qtv_samp_sizes);
640 	else if (qt_s_flag)
641 		QT_Read_STSZ(xin,len,&qts_samp_num,&qts_samp_sizes);
642 	else xin->Seek_FPos(xin,(len-8),1);
643 	file_len -= len;
644 	break;
645       case QT_stsc:
646 	if (qt_v_flag) QT_Read_STSC(xin,len,&qtv_s2chunk_num,&qtv_s2chunks,
647 			qtv_chunkoff_lstnum,qtv_codec_num,qtv_codec_lstnum);
648 	else if (qt_s_flag) QT_Read_STSC(xin,len,&qts_s2chunk_num,&qts_s2chunks,
649 			qts_chunkoff_lstnum,qts_codec_num,qts_codec_lstnum);
650 	else xin->Seek_FPos(xin,(len-8),1);
651 	file_len -= len;
652 	break;
653       case QT_stgs:
654 	QT_Read_STGS(xin,len);
655 	file_len -= len;
656 	break;
657     /*-----------Sound Codec Headers--------------*/
658       case QT_raw00:
659     /*-----------Video/Sound Codec Headers--------------*/
660       case QT_raw:
661     /*-----------Video Codec Headers--------------*/
662       case QT_smc:
663       case QT_rpza:
664       case QT_rle:
665       case QT_cvid:
666 	fprintf(stdout,"QT: Warning %08x\n",id);
667         xin->Seek_FPos(xin,(len-8),1);  /* skip over */
668 	file_len -= len;
669 	break;
670     /*-----------TYPE OF TRAK---------------*/
671       case QT_vmhd:
672         xin->Seek_FPos(xin,(len-8),1);
673 	file_len -= len; qt_v_flag = 1;
674 	qt_vid_timescale = qt_md_timescale;
675 	qtv_tk_timescale = qt_tk_timescale;
676 	qtv_init_duration = qt_init_duration; qt_init_duration = 0;
677 	qtv_start_offset = qt_start_offset; qt_start_offset = 0;
678 	break;
679       case QT_smhd:
680         xin->Seek_FPos(xin,(len-8),1);
681 	file_len -= len; qt_s_flag = 1;
682 	qt_aud_timescale = qt_md_timescale;
683 	qts_tk_timescale = qt_tk_timescale;
684 	qts_init_duration = qt_init_duration; qt_init_duration = 0;
685 	qts_start_offset = qt_start_offset; qt_start_offset = 0;
686 	break;
687     /************ CTAB ******************
688      * Color Table to be used for display 16/24 bit animations on
689      * 8 Bit displays.
690      *************************************/
691       case QT_ctab:
692 	{ xaULONG i,tmp,start,end;
693           if (x11_display_type != XA_PSEUDOCOLOR)
694 	  {
695 	     while(len > 0) {xin->Read_U8(xin); len--; }
696 	     break;
697 	  }
698 if (xa_verbose) fprintf(stdout,"QT: has ctab\n");
699           tmp   = xin->Read_MSB_U32(xin);  /* ?? */
700           start = xin->Read_MSB_U16(xin);  /* start */
701           end   = xin->Read_MSB_U16(xin);  /* end */
702 	  len -= 8;
703 	  for(i=start; i <= end; i++)
704 	  { xaULONG idx,r,g,b;
705 	    idx = xin->Read_MSB_U16(xin);
706 	    r   = xin->Read_MSB_U16(xin);
707 	    g   = xin->Read_MSB_U16(xin);
708 	    b   = xin->Read_MSB_U16(xin);  len -= 8;
709 	    /* if (cflag & 0x8000)  idx = i; */
710 	    if (idx < qt->imagec)
711 	    {
712 	      qt->cmap[idx].red   = r;
713 	      qt->cmap[idx].green = g;
714 	      qt->cmap[idx].blue  = b;
715 	    }
716 	    if (len <= 0) break;
717 	  } /* end of for i */
718 	  while(len > 0) {xin->Read_U8(xin); len--; }
719 	  qt->imagec = 256;
720 	  qt->chdr = ACT_Get_CMAP(qt->cmap,qt->imagec,0,qt->imagec,0,8,8,8);
721 	  qt_has_ctab = xaTRUE;
722 	}
723 	break;
724     /*--------------Indicated We Don't Support this File -----------*/
725       case QT_rmra:
726 	fprintf(stdout,"NOTE: RMRA chunk is not yet supported.\n");
727         xin->Seek_FPos(xin,(len-8),1);  /* skip over */
728 	file_len -= len;
729 	break;
730 /*
731 00000000: 00000AAC 636D7664 00001A0C 789CB598   ....cmvd....x...
732 00000010: 7B7054D5 1DC7BF1B 486049C8 3BEC665F   {pT.....H`I.;.f_
733 */
734       case QT_cmov:
735 	{ unsigned char *cmov_buf = 0;
736 	  unsigned char *moov_buf = 0;
737 	  int cmov_ret = xaFALSE;
738 	  int tlen, cmov_sz,moov_sz;
739 	  xaULONG cmov_comp = 0;
740 	  XA_INPUT	mem_xin;
741 
742 	  file_len -= len;
743 
744 	  len -= 8;
745 	  while(len > 8)
746 	  { xaULONG t_id, t_sz;
747 
748 	    t_sz = xin->Read_MSB_U32(xin);
749 	    t_id = xin->Read_MSB_U32(xin);
750 
751 	    len -= 8;
752 	    t_sz -= 8;
753 	  DEBUG_LEVEL1 fprintf(stderr,"QT CMOV: id %08x len %08x\n",t_id,t_sz);
754 
755 	    if (len < t_sz)
756 	    { fprintf(stderr,"QT err parsing cmov\n");
757 	      break;
758 	    }
759 	    len -= t_sz;
760 	    switch(t_id)
761 	    {
762 		/* Find out how cmov is compressed */
763 	      case QT_dcom:
764 		cmov_comp = xin->Read_MSB_U32(xin);	t_sz -= 4;
765 		if (cmov_comp != QT_zlib)
766 		{ fprintf(stderr,"QT cmov: unsupported compression %08x\n",
767 							cmov_comp);
768 		  fprintf(stderr,"         contact author.\n");
769 		  break;
770 		}
771 		else if (xa_verbose)
772 		{
773 		  fprintf(stdout,"  QT Compressed Hdr Codec: zlib\n");
774 		}
775 		if (t_sz > 0) { xin->Seek_FPos(xin,t_sz,1); t_sz = 0; }
776 		break;
777 
778 	      case QT_cmvd:
779 			/* read how large uncompressed moov will be */
780 		moov_sz = xin->Read_MSB_U32(xin); t_sz -= 4;
781 		cmov_sz = t_sz;
782 
783 			/* Allocate buffer for compressed header */
784 		cmov_buf = (unsigned char *)malloc( cmov_sz );
785 		if (cmov_buf == 0) TheEnd1("QT cmov: malloc err 0");
786 			/* Read in  compressed header */
787 		tlen = xin->Read_Block(xin, cmov_buf, cmov_sz);
788 		if (tlen != cmov_sz)
789 		{ fprintf(stderr,"QT cmov: read err\n");
790 		  free(cmov_buf);
791 		  return(xaFALSE);
792 		}
793 			/* Allocate buffer for decompressed header */
794 		moov_sz += 16; /* slop?? */
795 		moov_buf = (unsigned char *)malloc( moov_sz );
796 		if (moov_buf == 0) TheEnd1("QT cmov: malloc err 1");
797 
798 #ifndef XA_ZLIB
799 	  	  fprintf(stderr,
800 			"QT: cmov support not compiled in. See zlib.readme\n");
801 		  break;
802 #else
803 		{ z_stream zstrm;
804 		  int zret;
805 
806   		  zstrm.zalloc          = (alloc_func)0;
807   		  zstrm.zfree           = (free_func)0;
808   		  zstrm.opaque          = (voidpf)0;
809   		  zstrm.next_in         = cmov_buf;
810   		  zstrm.avail_in        = cmov_sz;
811   		  zstrm.next_out        = moov_buf;
812   		  zstrm.avail_out       = moov_sz;
813 
814   		  zret = inflateInit(&zstrm);
815   		  if (zret != Z_OK)
816 	          { fprintf(stderr,"QT cmov: inflateInit err %d\n",zret);
817 		    break;
818 		  }
819   		  zret = inflate(&zstrm, Z_NO_FLUSH);
820 		  if ((zret != Z_OK) && (zret != Z_STREAM_END))
821 	          { fprintf(stderr,"QT cmov inflate: ERR %d\n",zret);
822 		    break;
823 		  }
824 		  moov_sz = zstrm.total_out;
825   		  zret = inflateEnd(&zstrm);
826 
827 		  XA_Mem_Open_Init(&mem_xin,moov_buf,moov_sz);
828 		  cmov_ret = QT_Parse_Chunks(anim_hdr,qt,&mem_xin);
829 		  DEBUG_LEVEL1 fprintf(stderr,"QT cmov parse %d\n",cmov_ret);
830 		}
831 #endif
832 		break;
833 
834 	      default:
835 		fprintf(stderr,"QT CMOV: Unk chunk %08x \n",t_id);
836 		if (t_sz > 0) { xin->Seek_FPos(xin,t_sz,1); t_sz = 0; }
837 		break;
838 
839 	    } /* end of cmov sub chunk ID case */
840 	  } /* end of while len  */
841 	  if (cmov_buf) free(cmov_buf);
842 	  if (moov_buf) free(moov_buf);
843           if (cmov_ret == xaFALSE) return(cmov_ret); /*failed or unsupported*/
844 	} /* end of cmov */
845 	break;
846     /*--------------IGNORED FOR NOW---------*/
847       case QT_gmhd:
848       case QT_text:
849       case QT_clip:
850       case QT_skip:
851       case QT_free:
852       case QT_udta:
853       case QT_dinf:
854         xin->Seek_FPos(xin,(len-8),1);  /* skip over */
855 	file_len -= len;
856 	break;
857     /*--------------UNKNOWN-----------------*/
858       default:
859 	if ( !xin->At_EOF(xin) && (len <= file_len) )
860 	{
861 	  xaLONG i;
862 
863 DEBUG_LEVEL1
864 {
865 	  QT_Print_ID(stdout,id,1);
866 	  fprintf(stdout," len = %x file_len %x\n",len,file_len);
867 }
868 	  i = (xaLONG)(len) - 8;
869 		/* read and check eof */
870 	  while(i > 0) { i--; xin->Read_U8(xin); if (xin->At_EOF(xin)) i = 0; }
871 	}
872 	file_len -= len;
873 	break;
874     } /* end of switch */
875 
876     if ( xin->At_EOF(xin) )
877     {
878       file_len = 0;
879       if ((qt_moov_flag == xaFALSE) && (qt_data_flag == xaTRUE))
880       { fprintf(stdout,"QT: file possibly truncated or missing .rsrc info.\n");
881 	return(xaFALSE);
882       }
883     }
884     else if (file_len <= 0)
885     {
886 	/* interesting dilemma */
887       if (   (qt_data_flag == xaFALSE)
888 	  || (qt_moov_flag == xaFALSE))
889       {
890 	/** START OVER **/
891 	file_len = 1;
892       }
893     }
894   } /* end of while */
895   return(xaTRUE);
896 }
897 
QT_Print_ID(fout,id,flag)898 void QT_Print_ID(fout,id,flag)
899 FILE *fout;
900 xaLONG id,flag;
901 { fprintf(fout,"%c",     (char)((id >> 24) & 0xff));
902   fprintf(fout,"%c",     (char)((id >> 16) & 0xff));
903   fprintf(fout,"%c",     (char)((id >>  8) & 0xff));
904   fprintf(fout,"%c",     (char) (id        & 0xff));
905   if (flag) fprintf(fout,"(%x)",id);
906 }
907 
908 
QT_Read_MVHD(xin,qt_mvhdr)909 void QT_Read_MVHD(xin,qt_mvhdr)
910 XA_INPUT *xin;
911 QT_MVHDR *qt_mvhdr;
912 {
913   xaULONG i,j;
914 
915   qt_mvhdr->version =	xin->Read_MSB_U32(xin);
916   qt_mvhdr->creation =	xin->Read_MSB_U32(xin);
917   qt_mvhdr->modtime =	xin->Read_MSB_U32(xin);
918   qt_mvhdr->timescale =	xin->Read_MSB_U32(xin);
919   qt_mvhdr->duration =	xin->Read_MSB_U32(xin);
920   qt_mvhdr->rate =	xin->Read_MSB_U32(xin);
921   qt_mvhdr->volume =	xin->Read_MSB_U16(xin);
922   qt_mvhdr->r1  =	xin->Read_MSB_U32(xin);
923   qt_mvhdr->r2  =	xin->Read_MSB_U32(xin);
924   for(i=0;i<3;i++) for(j=0;j<3;j++)
925 	qt_mvhdr->matrix[i][j]=xin->Read_MSB_U32(xin);
926   qt_mvhdr->r3  =	xin->Read_MSB_U16(xin);
927   qt_mvhdr->r4  =	xin->Read_MSB_U32(xin);
928   qt_mvhdr->pv_time =	xin->Read_MSB_U32(xin);
929   qt_mvhdr->post_time =	xin->Read_MSB_U32(xin);
930   qt_mvhdr->sel_time =	xin->Read_MSB_U32(xin);
931   qt_mvhdr->sel_durat =	xin->Read_MSB_U32(xin);
932   qt_mvhdr->cur_time =	xin->Read_MSB_U32(xin);
933   qt_mvhdr->nxt_tk_id =	xin->Read_MSB_U32(xin);
934 
935   if (qt_mvhdr->timescale) qt_mv_timescale = qt_mvhdr->timescale;
936   else qt_mv_timescale = 1000;
937   qt_vid_timescale = qt_mv_timescale;
938 
939 
940   DEBUG_LEVEL2
941   { fprintf(stdout,"mv   ver = %x  timescale = %x  duration = %x\n",
942 	qt_mvhdr->version,qt_mvhdr->timescale, qt_mvhdr->duration);
943     fprintf(stdout,"     rate = %x volume = %x  nxt_tk = %x\n",
944 	qt_mvhdr->rate,qt_mvhdr->volume,qt_mvhdr->nxt_tk_id);
945   }
946 }
947 
QT_Read_TKHD(xin,qt_tkhdr)948 void QT_Read_TKHD(xin,qt_tkhdr)
949 XA_INPUT *xin;
950 QT_TKHDR *qt_tkhdr;
951 { xaULONG i,j;
952 
953   qt_tkhdr->version =	xin->Read_MSB_U32(xin);
954   qt_tkhdr->creation =	xin->Read_MSB_U32(xin);
955   qt_tkhdr->modtime =	xin->Read_MSB_U32(xin);
956   qt_tkhdr->trackid =	xin->Read_MSB_U32(xin);
957   qt_tkhdr->timescale =	xin->Read_MSB_U32(xin);
958   qt_tkhdr->duration =	xin->Read_MSB_U32(xin);
959   qt_tkhdr->time_off =	xin->Read_MSB_U32(xin);
960   qt_tkhdr->priority  =	xin->Read_MSB_U32(xin);
961   qt_tkhdr->layer  =	xin->Read_MSB_U16(xin);
962   qt_tkhdr->alt_group = xin->Read_MSB_U16(xin);
963   qt_tkhdr->volume  =	xin->Read_MSB_U16(xin);
964   for(i=0;i<3;i++) for(j=0;j<3;j++)
965 			qt_tkhdr->matrix[i][j]=xin->Read_MSB_U32(xin);
966   qt_tkhdr->tk_width =	xin->Read_MSB_U32(xin);
967   qt_tkhdr->tk_height =	xin->Read_MSB_U32(xin);
968   qt_tkhdr->pad  =	xin->Read_MSB_U16(xin);
969 
970   if (qt_tkhdr->timescale) qt_tk_timescale = qt_tkhdr->timescale;
971   else qt_tk_timescale = qt_mv_timescale;
972 
973   DEBUG_LEVEL2
974   { fprintf(stdout,"tk   ver = %x  tk_id = %x  timescale = %x\n",
975 	qt_tkhdr->version,qt_tkhdr->trackid,qt_tkhdr->timescale);
976     fprintf(stdout,"     dur= %x timoff= %x tk_width= %x  tk_height= %x\n",
977 	qt_tkhdr->duration,qt_tkhdr->time_off,qt_tkhdr->tk_width,qt_tkhdr->tk_height);
978   }
979 }
980 
981 
982 /* POD TODO */
983 /* implement difference between start_offset and init_duration */
QT_Read_ELST(xin,qt_start_offset,qt_init_duration)984 void QT_Read_ELST(xin,qt_start_offset,qt_init_duration)
985 XA_INPUT *xin;
986 xaULONG  *qt_start_offset;
987 xaULONG  *qt_init_duration;
988 { xaULONG i,num,version;
989 
990  version = xin->Read_MSB_U32(xin);
991  num = xin->Read_MSB_U32(xin);
992  DEBUG_LEVEL2 fprintf(stdout,"    ELST ver %x num %x\n",version,num);
993  for(i=0; i < num; i++)
994  { xaULONG duration,time,rate,pad;
995    duration = xin->Read_MSB_U32(xin);
996    time = xin->Read_MSB_U32(xin);
997    rate = xin->Read_MSB_U16(xin);
998    pad  = xin->Read_MSB_U16(xin);
999 
1000 /* This is currently a kludge with limited support */
1001    if (i==0)
1002    {  if (time == 0xffffffff)	*qt_init_duration += duration;
1003       else if (time != 0x0)	*qt_start_offset += time;
1004    }
1005    DEBUG_LEVEL2 fprintf(stdout,"    -) dur %x tim %x rate %x\n",
1006 		duration,time,rate);
1007  }
1008 }
1009 
QT_Read_MDHD(xin,qt_mdhdr)1010 void QT_Read_MDHD(xin,qt_mdhdr)
1011 XA_INPUT *xin;
1012 QT_MDHDR *qt_mdhdr;
1013 { qt_mdhdr->version =	xin->Read_MSB_U32(xin);
1014   qt_mdhdr->creation =	xin->Read_MSB_U32(xin);
1015   qt_mdhdr->modtime =	xin->Read_MSB_U32(xin);
1016   qt_mdhdr->timescale =	xin->Read_MSB_U32(xin);
1017   qt_mdhdr->duration =	xin->Read_MSB_U32(xin);
1018   qt_mdhdr->language =	xin->Read_MSB_U16(xin);
1019   qt_mdhdr->quality =	xin->Read_MSB_U16(xin);
1020 
1021   if (qt_mdhdr->timescale) qt_md_timescale = qt_mdhdr->timescale;
1022   else qt_md_timescale = qt_tk_timescale;
1023 
1024   DEBUG_LEVEL2
1025   { fprintf(stdout,"md   ver = %x  timescale = %x  duration = %x\n",
1026 	qt_mdhdr->version,qt_mdhdr->timescale,qt_mdhdr->duration);
1027     fprintf(stdout,"     lang= %x quality= %x\n",
1028 	qt_mdhdr->language,qt_mdhdr->quality);
1029   }
1030 }
1031 
1032 
QT_Read_HDLR(xin,len,qt_hdlr_hdr)1033 void QT_Read_HDLR(xin,len,qt_hdlr_hdr)
1034 XA_INPUT *xin;
1035 xaLONG len;
1036 QT_HDLR_HDR *qt_hdlr_hdr;
1037 { qt_hdlr_hdr->version =	xin->Read_MSB_U32(xin);
1038   qt_hdlr_hdr->type =	xin->Read_MSB_U32(xin);
1039   qt_hdlr_hdr->subtype =	xin->Read_MSB_U32(xin);
1040   qt_hdlr_hdr->vendor =	xin->Read_MSB_U32(xin);
1041   qt_hdlr_hdr->flags =	xin->Read_MSB_U32(xin);
1042   qt_hdlr_hdr->mask =	xin->Read_MSB_U32(xin);
1043 
1044   DEBUG_LEVEL2
1045   { fprintf(stdout,"     ver = %x  ",qt_hdlr_hdr->version);
1046     QT_Print_ID(stdout,qt_hdlr_hdr->type,1);
1047     QT_Print_ID(stdout,qt_hdlr_hdr->subtype,1);
1048     QT_Print_ID(stdout,qt_hdlr_hdr->vendor,0);
1049     fprintf(stdout,"\n     flags= %x mask= %x\n",
1050 	qt_hdlr_hdr->flags,qt_hdlr_hdr->mask);
1051   }
1052   /* Read Handler Name if Present */
1053   if (len > 32)
1054   { len -= 32;
1055     QT_Read_Name(xin,len);
1056   }
1057 }
1058 
1059 
1060 /*********************************************
1061  * Read and Parse Video Codecs
1062  *
1063  **********/
QT_Read_Video_STSD(anim_hdr,qt,xin,clen)1064 xaULONG QT_Read_Video_STSD(anim_hdr,qt,xin,clen)
1065 XA_ANIM_HDR	*anim_hdr;
1066 XA_ANIM_SETUP	*qt;
1067 XA_INPUT		*xin;
1068 xaLONG		clen;
1069 { xaULONG i,version,num,cur,sup;
1070   version = xin->Read_MSB_U32(xin);
1071   num = xin->Read_MSB_U32(xin);
1072   clen -= 8;
1073   DEBUG_LEVEL2 fprintf(stdout,"     ver = %x  num = %x\n", version,num);
1074   if (qtv_codecs == 0)
1075   { qtv_codec_num = num;
1076     qtv_codecs = (QTV_CODEC_HDR *)malloc(qtv_codec_num * sizeof(QTV_CODEC_HDR));
1077     if (qtv_codecs==0) TheEnd1("QT STSD: malloc err");
1078     cur = 0;
1079   }
1080   else
1081   { QTV_CODEC_HDR *tcodecs;
1082     tcodecs = (QTV_CODEC_HDR *)malloc((qtv_codec_num+num) * sizeof(QTV_CODEC_HDR));
1083     if (tcodecs==0) TheEnd1("QT STSD: malloc err");
1084     for(i=0;i<qtv_codec_num;i++) tcodecs[i] = qtv_codecs[i];
1085     cur = qtv_codec_num;
1086     qtv_codec_num += num;
1087     FREE(qtv_codecs,0x900d);
1088     qtv_codecs = tcodecs;
1089   }
1090   sup = 0;
1091   for(i=0; i < num; i++)
1092   {
1093     sup |= QT_Read_Video_Codec_HDR(anim_hdr,qt, &qtv_codecs[cur], xin, &clen );
1094 DEBUG_LEVEL1 fprintf(stdout,"CODEC %d) sup=%d\n",i,sup);
1095     cur++;
1096   }
1097   if (clen)
1098   { DEBUG_LEVEL1 fprintf(stdout,"QT Video STSD len mismatch %x\n",clen);
1099     xin->Seek_FPos(xin,clen,1);
1100   }
1101 
1102   if (sup == 0) return(xaFALSE);
1103   qt_video_flag = 1;
1104   if ( (qt->pic==0) && (xa_buffer_flag == xaTRUE))
1105   {
1106     qt->pic_size = qt->max_imagex * qt->max_imagey;
1107     if ( (cmap_true_map_flag == xaTRUE) && (qt->depth > 8) )
1108 		qt->pic = (xaUBYTE *) malloc(3 * qt->pic_size);
1109     else	qt->pic = (xaUBYTE *) malloc( XA_PIC_SIZE(qt->pic_size) );
1110     if (qt->pic == 0) TheEnd1("QT_Buffer_Action: malloc failed");
1111   }
1112   return(xaTRUE);
1113 }
1114 
1115 
QT_Read_Video_Codec_HDR(anim_hdr,qt,c_hdr,xin,clen)1116 xaULONG QT_Read_Video_Codec_HDR(anim_hdr,qt,c_hdr,xin, clen)
1117 XA_ANIM_HDR *anim_hdr;
1118 XA_ANIM_SETUP *qt;
1119 QTV_CODEC_HDR *c_hdr;
1120 XA_INPUT *xin;
1121 xaLONG		*clen;
1122 {
1123   xaULONG id;
1124   xaLONG len,i,codec_ret;
1125   xaULONG unk_0,unk_1,unk_2,unk_3,unk_4,unk_5,unk_6,unk_7,flag;
1126   xaULONG vendor,temp_qual,spat_qual,h_res,v_res;
1127 
1128   len		= xin->Read_MSB_U32(xin);
1129   *clen		-= len;
1130   id 		= xin->Read_MSB_U32(xin);
1131   unk_0		= xin->Read_MSB_U32(xin);
1132   unk_1		= xin->Read_MSB_U32(xin);
1133   unk_2		= xin->Read_MSB_U16(xin);
1134   unk_3		= xin->Read_MSB_U16(xin);
1135   vendor	= xin->Read_MSB_U32(xin);
1136   temp_qual	= xin->Read_MSB_U32(xin);
1137   spat_qual	= xin->Read_MSB_U32(xin);
1138   qt->imagex	= xin->Read_MSB_U16(xin);
1139   qt->imagey	= xin->Read_MSB_U16(xin);
1140   h_res		= xin->Read_MSB_U16(xin);
1141   unk_4		= xin->Read_MSB_U16(xin);
1142   v_res		= xin->Read_MSB_U16(xin);
1143   unk_5		= xin->Read_MSB_U16(xin);
1144   unk_6		= xin->Read_MSB_U32(xin);
1145   unk_7		= xin->Read_MSB_U16(xin);
1146   QT_Read_Name(xin,32);
1147   qt->depth	= xin->Read_MSB_U16(xin);
1148   flag		= xin->Read_MSB_U16(xin);
1149   len -= 0x56;
1150 
1151   /* init now in case of early out */
1152   c_hdr->width	= qt->imagex;
1153   c_hdr->height	= qt->imagey;
1154   c_hdr->depth	= qt->depth;
1155   c_hdr->compression = id;
1156   c_hdr->chdr	= 0;
1157 
1158   if (   (qt->depth == 8) || (qt->depth == 40)
1159       || (qt->depth == 4) || (qt->depth == 36)
1160       || (qt->depth == 2) || (qt->depth == 34) ) /* generate colormap */
1161   {
1162     if      ((qt->depth & 0x0f) == 0x04) qt->imagec = 16;
1163     else if ((qt->depth & 0x0f) == 0x02) qt->imagec = 4;
1164     else				 qt->imagec = 256;
1165 
1166     if ((qt->depth < 32) && (id != QT_raw3))
1167     {
1168       QT_Create_Default_Cmap(qt->cmap,qt->imagec);
1169     }
1170     else /* grayscale */
1171     {
1172       if ((id == QT_jpeg) || (id == QT_cvid) || (id == QT_raw3))
1173 		QT_Create_Gray_Cmap(qt->cmap,1,qt->imagec);
1174       else	QT_Create_Gray_Cmap(qt->cmap,0,qt->imagec);
1175     }
1176 
1177     if ( !(flag & 0x08) && (len) ) /* colormap isn't default */
1178     {
1179       xaULONG start,end,p,r,g,b,cflag;
1180 DEBUG_LEVEL1 fprintf(stdout,"reading colormap. flag %x\n",flag);
1181       start = xin->Read_MSB_U32(xin); /* is this start or something else? */
1182       cflag = xin->Read_MSB_U16(xin); /* is this end or total number? */
1183       end   = xin->Read_MSB_U16(xin); /* is this end or total number? */
1184       len -= 8;
1185 DEBUG_LEVEL1 fprintf(stdout," start %x end %x cflag %x\n",start,end,cflag);
1186       for(i = start; i <= end; i++)
1187       {
1188         p = xin->Read_MSB_U16(xin);
1189         r = xin->Read_MSB_U16(xin);
1190         g = xin->Read_MSB_U16(xin);
1191         b = xin->Read_MSB_U16(xin);  len -= 8;
1192         if (cflag & 0x8000) p = i;
1193         if (p<qt->imagec)
1194         {
1195 	  qt->cmap[p].red   = r;
1196 	  qt->cmap[p].green = g;
1197 	  qt->cmap[p].blue  = b;
1198         }
1199         if (len <= 0) break;
1200       }
1201     }
1202   }
1203 
1204   if (len)
1205   { xin->Seek_FPos(xin,len,1);
1206     len = 0;
1207   }
1208 
1209   qt->compression = qt_codec_hdr.compression = id;
1210   qt_codec_hdr.x = qt->imagex;
1211   qt_codec_hdr.y = qt->imagey;
1212   qt_codec_hdr.depth = qt->depth;
1213   qt_codec_hdr.anim_hdr = (void *)anim_hdr;
1214   qt_codec_hdr.avi_ctab_flag = xaFALSE;
1215 
1216   /* Query to see if Video Compression is supported or not */
1217   codec_ret = QT_Video_Codec_Query( &qt_codec_hdr );
1218   if (codec_ret == CODEC_SUPPORTED)
1219   {
1220     qt->imagex		= qt_codec_hdr.x;
1221     qt->imagey		= qt_codec_hdr.y;
1222     qt->depth		= qt_codec_hdr.depth;
1223     qt->compression	= qt_codec_hdr.compression;
1224     c_hdr->xapi_rev	= qt_codec_hdr.xapi_rev;
1225     c_hdr->decoder	= qt_codec_hdr.decoder;
1226     c_hdr->depth 	= qt_codec_hdr.depth;		/* depth */
1227     c_hdr->dlta_extra	= qt_codec_hdr.extra;
1228   }
1229   else /*** Return False if Codec is Unknown or Not Supported */
1230   /* if (codec_ret != CODEC_SUPPORTED) */
1231   { char tmpbuf[256];
1232     if (codec_ret == CODEC_UNKNOWN)
1233     { xaULONG ii,a[4],dd = qt->compression;
1234       for(ii=0; ii<4; ii++)
1235       { a[ii] = dd & 0xff;  dd >>= 8;
1236         if ((a[ii] < ' ') || (a[ii] > 'z')) a[ii] = '.';
1237       }
1238       sprintf(tmpbuf,"Unknown %c%c%c%c(%08x)",
1239 		(char)a[3],(char)a[2],(char)a[1],(char)a[0],qt->compression);
1240       qt_codec_hdr.description = tmpbuf;
1241     }
1242     fprintf(stdout,"  Video Codec: %s",qt_codec_hdr.description);
1243     fprintf(stdout," not yet supported.(E%x)\n",qt->depth);
1244 /* point 'em to the readme's */
1245     switch(qt->compression)
1246     {
1247       case QT_iv31:
1248       case QT_IV31:
1249       case QT_iv32:
1250       case QT_IV32:
1251       case QT_YVU9:
1252       case QT_YUV9:
1253         fprintf(stdout,"      To support this Codec please read the file \"indeo.readme\".\n");
1254         break;
1255       case QT_cvid:
1256       case QT_CVID:
1257         fprintf(stdout,"      To support this Codec please read the file \"cinepak.readme\".\n");
1258         break;
1259     }
1260     return(0);
1261   }
1262   if (qt->depth == 40) qt->depth = 8;
1263 
1264   /* Print out Video Codec info */
1265   if (xa_verbose) fprintf(stdout,"  Video Codec: %s depth=%d\n",
1266                                 qt_codec_hdr.description,qt->depth);
1267 
1268 
1269   if (qt->depth == 1)
1270   {
1271     qt->imagec = 2;
1272     qt->cmap[0].red = qt->cmap[0].green = qt->cmap[0].blue = 0;
1273     qt->cmap[1].red = qt->cmap[1].green = qt->cmap[1].blue = 0xff;
1274     qt->chdr = ACT_Get_CMAP(qt->cmap,qt->imagec,0,qt->imagec,0,8,8,8);
1275   }
1276   else if ((qt->depth == 8) || (qt->depth == 4))
1277   {
1278     qt->chdr = ACT_Get_CMAP(qt->cmap,qt->imagec,0,qt->imagec,0,16,16,16);
1279   }
1280   else if ( (qt->depth >= 16) && (qt->depth <= 32) )
1281   {
1282     if (   (cmap_true_map_flag == xaFALSE) /* depth 16 and not true_map */
1283            || (xa_buffer_flag == xaFALSE) )
1284     {
1285       if (cmap_true_to_332 == xaTRUE)
1286 		qt->chdr = CMAP_Create_332(qt->cmap,&qt->imagec);
1287       else	qt->chdr = CMAP_Create_Gray(qt->cmap,&qt->imagec);
1288     }
1289     else { qt->imagec = 0; qt->chdr = 0; }
1290   }
1291   c_hdr->width	= qt->imagex;
1292   c_hdr->height	= qt->imagey;
1293   c_hdr->depth	= qt->depth;
1294   c_hdr->compression = qt->compression;
1295   c_hdr->chdr	= qt->chdr;
1296   if (qt->imagex > qt->max_imagex) qt->max_imagex = qt->imagex;
1297   if (qt->imagey > qt->max_imagey) qt->max_imagey = qt->imagey;
1298   return(1);
1299 }
1300 
QT_Read_Name(xin,r_len)1301 void QT_Read_Name(xin,r_len)
1302 XA_INPUT *xin;
1303 xaLONG r_len;
1304 {
1305   xaULONG len,d,i;
1306 
1307   len = xin->Read_U8(xin); r_len--;
1308   if (r_len == 0) r_len = len;
1309   if (len > r_len) fprintf(stdout,"QT_Name: len(%d) > r_len(%d)\n",len,r_len);
1310   DEBUG_LEVEL2 fprintf(stdout,"      (%d/%d) ",len,r_len);
1311   for(i=0;i<r_len;i++)
1312   {
1313     d = xin->Read_U8(xin) & 0x7f;
1314     if (i < len) DEBUG_LEVEL2 fputc(d,stdout);
1315   }
1316   DEBUG_LEVEL2 fputc('\n',stdout);
1317 }
1318 
1319 /* Time To Sample */
QT_Read_STTS(xin,len,qt_t2samp_num,qt_t2samps)1320 void QT_Read_STTS(xin,len,qt_t2samp_num,qt_t2samps)
1321 XA_INPUT *xin;
1322 xaLONG len;
1323 xaULONG *qt_t2samp_num;
1324 QT_T2SAMP_HDR **qt_t2samps;
1325 {
1326   xaULONG version,num,i,samp_cnt,duration,cur;
1327   xaULONG t2samp_num = *qt_t2samp_num;
1328   QT_T2SAMP_HDR *t2samps = *qt_t2samps;
1329 
1330   version	= xin->Read_MSB_U32(xin);
1331   num		= xin->Read_MSB_U32(xin);  len -= 8;
1332   DEBUG_LEVEL2 fprintf(stdout,"    ver=%x num of entries = %x\n",version,num);
1333 /* POD TEST chunk len/num mismatch - deal with it - ignore given num??*/
1334   num = len >> 3;
1335   if (t2samps==0)
1336   {
1337     t2samp_num = num;
1338     t2samps = (QT_T2SAMP_HDR *)malloc(num * sizeof(QT_T2SAMP_HDR));
1339     if (t2samps==0) TheEnd1("QT_Read_STTS: malloc err");
1340     cur = 0;
1341   }
1342   else
1343   { QT_T2SAMP_HDR *t_t2samp;
1344     t_t2samp = (QT_T2SAMP_HDR *)
1345 			malloc((t2samp_num + num) * sizeof(QT_T2SAMP_HDR));
1346     if (t_t2samp==0) TheEnd1("QT_Read_STTS: malloc err");
1347     for(i=0;i<t2samp_num;i++) t_t2samp[i] = t2samps[i];
1348     cur = t2samp_num;
1349     t2samp_num += num;
1350     FREE(t2samps,0x900e);
1351     t2samps = t_t2samp;
1352   }
1353   for(i=0;i<num;i++)
1354   { double ftime;
1355     samp_cnt	= xin->Read_MSB_U32(xin);
1356     duration	= xin->Read_MSB_U32(xin);  len -= 8;
1357     if (duration == 0) duration = 1;
1358     /* NOTE: convert to 1000ms per second */
1359     t2samps[cur].cnt = samp_cnt;
1360     ftime = (1000.0 * (double)(duration)) / (double)(qt_vid_timescale);
1361     t2samps[cur].time = (xaULONG)(ftime);
1362     ftime -= (double)(t2samps[cur].time);
1363     t2samps[cur].timelo = (xaULONG)(ftime * (double)(1<<24));
1364     DEBUG_LEVEL2 fprintf(stdout,"      %d) samp_cnt=%x duration = %x time %d timelo %d ftime %f\n",
1365 	i,samp_cnt,duration,t2samps[cur].time,t2samps[cur].timelo,ftime);
1366     cur++;
1367   }
1368   *qt_t2samp_num = t2samp_num;
1369   *qt_t2samps = t2samps;
1370   while(len > 0) {len--; xin->Read_U8(xin); }
1371 }
1372 
1373 
1374 /* Sync Sample */
QT_Read_STSS(xin)1375 void QT_Read_STSS(xin)
1376 XA_INPUT *xin;
1377 {
1378   xaULONG version,num,i,j;
1379   version	= xin->Read_MSB_U32(xin);
1380   num		= xin->Read_MSB_U32(xin);
1381   DEBUG_LEVEL2
1382   {
1383     fprintf(stdout,"    ver=%x num of entries = %x\n",version,num);
1384     j = 0;
1385     fprintf(stdout,"      ");
1386   }
1387   for(i=0;i<num;i++)
1388   {
1389     xaULONG samp_num;
1390     samp_num	= xin->Read_MSB_U32(xin);
1391     DEBUG_LEVEL2
1392     {
1393       fprintf(stdout,"%x ",samp_num); j++;
1394       if (j >= 8) {fprintf(stdout,"\n      "); j=0; }
1395     }
1396   }
1397   DEBUG_LEVEL2 fprintf(stdout,"\n");
1398 }
1399 
1400 
1401 /* Sample to Chunk */
QT_Read_STSC(xin,len,qt_s2chunk_num,qt_s2chunks,chunkoff_lstnum,codec_num,codec_lstnum)1402 void QT_Read_STSC(xin,len,qt_s2chunk_num,qt_s2chunks,
1403 		chunkoff_lstnum,codec_num,codec_lstnum)
1404 XA_INPUT *xin;
1405 xaLONG len;
1406 xaULONG *qt_s2chunk_num;
1407 QT_S2CHUNK_HDR **qt_s2chunks;
1408 xaULONG chunkoff_lstnum,codec_num,codec_lstnum;
1409 {
1410   xaULONG version,num,i,cur,stsc_type,last;
1411   xaULONG s2chunk_num = *qt_s2chunk_num;
1412   QT_S2CHUNK_HDR *s2chunks = *qt_s2chunks;
1413 
1414   version	= xin->Read_MSB_U32(xin);
1415   num		= xin->Read_MSB_U32(xin);	len -= 16;
1416   i = (num)?(len/num):(0);
1417   if (i == 16)
1418   {
1419     DEBUG_LEVEL2 fprintf(stdout,"STSC: OLD STYLE\n");
1420     len -= num * 16; stsc_type = 0;
1421   }
1422   else
1423   {
1424     DEBUG_LEVEL2 fprintf(stdout,"STSC: NEW STYLE\n");
1425     len -= num * 12; stsc_type = 1;
1426   }
1427 
1428   DEBUG_LEVEL2 fprintf(stdout,"    ver=%x num of entries = %x\n",version,num);
1429   if (s2chunks == 0)
1430   {
1431     s2chunk_num = num;
1432     s2chunks = (QT_S2CHUNK_HDR *)malloc((num+1) * sizeof(QT_S2CHUNK_HDR));
1433     cur = 0;
1434   }
1435   else
1436   { QT_S2CHUNK_HDR *ts2c;
1437     ts2c = (QT_S2CHUNK_HDR *)
1438 	malloc( (s2chunk_num + num + 1) * sizeof(QT_S2CHUNK_HDR));
1439     for(i=0;i<s2chunk_num;i++) ts2c[i] = s2chunks[i];
1440     cur = s2chunk_num;
1441     s2chunk_num += num;
1442     FREE(s2chunks,0x900f);
1443     s2chunks = ts2c;
1444   }
1445   last = 0;
1446   for(i=0;i<num;i++)
1447   {
1448     xaULONG first_chk,samp_per,chunk_tag;
1449     if (stsc_type == 0)  /* 4 entries */
1450     { xaULONG tmp;
1451       first_chk	= xin->Read_MSB_U32(xin);
1452       tmp	= xin->Read_MSB_U32(xin);
1453       samp_per	= xin->Read_MSB_U32(xin);
1454       chunk_tag	= xin->Read_MSB_U32(xin);
1455       if (i > 0) s2chunks[cur-1].num   = first_chk - last;
1456       last = first_chk;
1457       if (i==(num-1))
1458       {
1459 	if (qt_stgs_num)
1460 	{
1461 	  s2chunks[cur].num   = (qt_stgs_num - first_chk) + 1;
1462 	  qt_stgs_num = 0;
1463         }
1464 	else
1465 	{
1466 	  fprintf(stdout,"STSC: old style but not stgs chunk warning\n");
1467 	  s2chunks[cur].num = 100000;
1468 	}
1469       }
1470     }
1471     else		/* 3 entries */
1472     {
1473       first_chk	= xin->Read_MSB_U32(xin);
1474       samp_per	= xin->Read_MSB_U32(xin);
1475       chunk_tag	= xin->Read_MSB_U32(xin);
1476       s2chunks[cur].num   = samp_per;
1477     }
1478     DEBUG_LEVEL2
1479      fprintf(stdout,"      %d-%d) first_chunk=%x samp_per_chk=%x chk_tag=%x\n",
1480 					i,cur,first_chk,samp_per,chunk_tag);
1481         /* start at 0 not 1  and account for previous chunks */
1482     s2chunks[cur].first = first_chk - 1 + chunkoff_lstnum;
1483     if (chunk_tag > (codec_num - codec_lstnum))
1484 	{ samp_per = chunk_tag = 1; }
1485     s2chunks[cur].tag   = chunk_tag - 1 + codec_lstnum;
1486     cur++;
1487   }
1488   s2chunks[cur].first = 0;
1489   s2chunks[cur].num   = 0;
1490   s2chunks[cur].tag   = 0;
1491   DEBUG_LEVEL2 fprintf(stdout,"    STSC left over %d\n",len);
1492   while (len > 0) { xin->Read_U8(xin); len--; }
1493   *qt_s2chunk_num = s2chunk_num;
1494   *qt_s2chunks = s2chunks;
1495 }
1496 
1497 /* Sample Size */
QT_Read_STSZ(xin,len,qt_samp_num,qt_samp_sizes)1498 void QT_Read_STSZ(xin,len,qt_samp_num,qt_samp_sizes)
1499 XA_INPUT *xin;
1500 xaLONG len;
1501 xaULONG *qt_samp_num,**qt_samp_sizes;
1502 {
1503   xaULONG version,samp_size,num,i,cur;
1504   xaULONG samp_num   = *qt_samp_num;
1505   xaULONG *samp_sizes = *qt_samp_sizes;
1506 
1507   version	= xin->Read_MSB_U32(xin);
1508   samp_size	= xin->Read_MSB_U32(xin);
1509   num		= xin->Read_MSB_U32(xin);
1510   len = (len - 20) / 4;   /* number of stored samples */
1511   DEBUG_LEVEL2 fprintf(stdout,"    ver=%x samp_size=%x entries= %x stored entries=%x\n",version,samp_size,num,len);
1512 
1513 #ifdef NO_MORE
1514   if (samp_size == 1) num = 1; /* for AUDIO PODNOTE: rethink this */
1515 #endif
1516 	/* Some quicktime files were created by idiots and list a
1517 	 * size entry for each audio sample.  If they're all the same
1518 	 * size there should only be one entry.
1519 	 */
1520   if (len < num) num = len;
1521   if (num == 0) num = 1;
1522 
1523   if (samp_sizes == 0)
1524   {
1525     samp_num = num;
1526     samp_sizes = (xaULONG *)malloc(num * sizeof(xaULONG));
1527     if (samp_sizes == 0) {fprintf(stdout,"malloc err 0\n"); TheEnd();}
1528     cur = 0;
1529   }
1530   else /*TRAK*/
1531   {
1532     xaULONG *tsamps;
1533     tsamps = (xaULONG *)malloc((samp_num + num) * sizeof(xaULONG));
1534     if (tsamps == 0) {fprintf(stdout,"malloc err 0\n"); TheEnd();}
1535     for(i=0; i<samp_num; i++) tsamps[i] = samp_sizes[i];
1536     cur = samp_num;
1537     samp_num += num;
1538     FREE(samp_sizes,0x9010);
1539     samp_sizes = tsamps;
1540   }
1541   for(i=0;i<num;i++)
1542   {
1543     if (i < len) samp_sizes[cur] = xin->Read_MSB_U32(xin);
1544     else if (i==0) samp_sizes[cur] = samp_size;
1545            else samp_sizes[cur] = samp_sizes[cur-1];
1546     cur++;
1547   }
1548   *qt_samp_num = samp_num;
1549   *qt_samp_sizes = samp_sizes;
1550 }
1551 
1552 /* Chunk Offset */
QT_Read_STCO(xin,qt_chunkoff_num,qt_chunkoffs)1553 void QT_Read_STCO(xin,qt_chunkoff_num,qt_chunkoffs)
1554 XA_INPUT *xin;
1555 xaULONG *qt_chunkoff_num;
1556 xaULONG **qt_chunkoffs;
1557 {
1558   xaULONG version,num,i,cur;
1559   xaULONG chunkoff_num = *qt_chunkoff_num;
1560   xaULONG *chunkoffs = *qt_chunkoffs;
1561 
1562   version	= xin->Read_MSB_U32(xin);
1563   num		= xin->Read_MSB_U32(xin);
1564   DEBUG_LEVEL2 fprintf(stdout,"    ver=%x entries= %x\n",version,num);
1565   if (chunkoffs == 0)
1566   {
1567     chunkoff_num = num;
1568     chunkoffs = (xaULONG *)malloc(num * sizeof(xaULONG) );
1569     cur = 0;
1570   }
1571   else
1572   {
1573     xaULONG *tchunks;
1574     tchunks = (xaULONG *)malloc((chunkoff_num + num) * sizeof(xaULONG));
1575     if (tchunks == 0) {fprintf(stdout,"malloc err 0\n"); TheEnd();}
1576     for(i=0; i<chunkoff_num; i++) tchunks[i] = chunkoffs[i];
1577     cur = chunkoff_num;
1578     chunkoff_num += num;
1579     FREE(chunkoffs,0x9011);
1580     chunkoffs = tchunks;
1581   }
1582   for(i=0;i<num;i++) {chunkoffs[cur] = xin->Read_MSB_U32(xin); cur++; }
1583   *qt_chunkoff_num = chunkoff_num;
1584   *qt_chunkoffs = chunkoffs;
1585  DEBUG_LEVEL2
1586  { for(i=0;i<num;i++)  fprintf(stdout,"  STCO %d) %x\n",i,
1587 		chunkoffs[ i ]);
1588  }
1589 }
1590 
1591 
1592 
QT_Read_Video_Data(qt,xin,anim_hdr)1593 xaULONG QT_Read_Video_Data(qt,xin,anim_hdr)
1594 XA_ANIM_SETUP *qt;
1595 XA_INPUT *xin;
1596 XA_ANIM_HDR *anim_hdr;
1597 {
1598   xaULONG d,ret,i;
1599   xaULONG cur_samp,cur_s2chunk,nxt_s2chunk;
1600   xaULONG cur_t2samp,nxt_t2samp;
1601   xaULONG tag;
1602   xaULONG cur_off;
1603   xaULONG unsupported_flag = xaFALSE;
1604   XA_ACTION *act;
1605 
1606   qtv_init_duration += qts_start_offset;
1607 
1608   qt->cmap_frame_num = qtv_chunkoff_num / cmap_sample_cnt;
1609 
1610   nxt_t2samp = cur_t2samp = 0;
1611   if (qtv_t2samps)
1612   {
1613     if (xa_jiffy_flag) { qt->vid_time = xa_jiffy_flag; qt->vid_timelo = 0; }
1614     else
1615     {
1616       qt->vid_time   = qtv_t2samps[cur_t2samp].time;
1617       qt->vid_timelo = qtv_t2samps[cur_t2samp].timelo;
1618     }
1619     nxt_t2samp += qtv_t2samps[cur_t2samp].cnt;
1620   } else { qt->vid_time = XA_GET_TIME(100); qt->vid_timelo = 0; }
1621 
1622   cur_off=0;
1623   cur_samp = 0;
1624   cur_s2chunk = 0;
1625   nxt_s2chunk = qtv_s2chunks[cur_s2chunk + 1].first;
1626   tag =  qtv_s2chunks[cur_s2chunk].tag;
1627   qt->imagex = qtv_codecs[tag].width;
1628   qt->imagey = qtv_codecs[tag].height;
1629   qt->depth  = qtv_codecs[tag].depth;
1630   qt->compression  = qtv_codecs[tag].compression;
1631   qt->chdr   = qtv_codecs[tag].chdr;
1632 
1633   /* Loop through chunk offsets */
1634   for(i=0; i < qtv_chunkoff_num; i++)
1635   {
1636     xaULONG size,chunk_off,num_samps;
1637     ACT_DLTA_HDR *dlta_hdr;
1638 
1639     chunk_off =  qtv_chunkoffs[i];
1640 
1641 /* survive RPZA despite corruption(offsets commonly corrupted).*/
1642 /* MOVE THIS INTO RPZA DECODE
1643    check size of RPZA again size in codec.
1644 */
1645 
1646     if ( (i == nxt_s2chunk) && ((cur_s2chunk+1) < qtv_s2chunk_num) )
1647     {
1648       cur_s2chunk++;
1649       nxt_s2chunk = qtv_s2chunks[cur_s2chunk + 1].first;
1650     }
1651     num_samps = qtv_s2chunks[cur_s2chunk].num;
1652 
1653     /* Check tags and possibly move to new codec */
1654     if (qtv_s2chunks[cur_s2chunk].tag >= qtv_codec_num)
1655     {
1656       fprintf(stdout,"QT Data: Warning stsc chunk invalid %d tag %d\n",
1657 		cur_s2chunk,qtv_s2chunks[cur_s2chunk].tag);
1658     }
1659     else if (qtv_s2chunks[cur_s2chunk].tag != tag)
1660     {
1661       tag =  qtv_s2chunks[cur_s2chunk].tag;
1662       qt->imagex = qtv_codecs[tag].width;
1663       qt->imagey = qtv_codecs[tag].height;
1664       qt->depth  = qtv_codecs[tag].depth;
1665       qt->compression  = qtv_codecs[tag].compression;
1666       qt->chdr   = qtv_codecs[tag].chdr;
1667     }
1668 
1669     /* Read number of samples in each chunk */
1670     cur_off = chunk_off;
1671     while(num_samps--)
1672     {
1673 
1674 DEBUG_LEVEL2 fprintf(stdout,"T2S: cur-t2 %d cur-smp %d nxt-t2 %d tot t2 %d\n", cur_t2samp,cur_samp,nxt_t2samp,qtv_t2samp_num);
1675     if ( (cur_samp >= nxt_t2samp) && (cur_t2samp < qtv_t2samp_num) )
1676     {
1677       cur_t2samp++;
1678       if (xa_jiffy_flag) { qt->vid_time = xa_jiffy_flag; qt->vid_timelo = 0; }
1679       else
1680       { qt->vid_time   = qtv_t2samps[cur_t2samp].time;
1681 	qt->vid_timelo = qtv_t2samps[cur_t2samp].timelo;
1682       }
1683       nxt_t2samp += qtv_t2samps[cur_t2samp].cnt;
1684     }
1685 
1686       size = qtv_samp_sizes[cur_samp];
1687 
1688       act = ACT_Get_Action(anim_hdr,ACT_DELTA);
1689       if (xa_file_flag == xaTRUE)
1690       {
1691 	dlta_hdr = (ACT_DLTA_HDR *) malloc(sizeof(ACT_DLTA_HDR));
1692 	if (dlta_hdr == 0) TheEnd1("QT rle: malloc failed");
1693 	act->data = (xaUBYTE *)dlta_hdr;
1694 	dlta_hdr->flags = ACT_SNGL_BUF;
1695 	dlta_hdr->fsize = size;
1696 	dlta_hdr->fpos  = cur_off;
1697 	if (size > qt->max_fvid_size) qt->max_fvid_size = size;
1698       }
1699       else
1700       {
1701 	d = size + (sizeof(ACT_DLTA_HDR));
1702 	dlta_hdr = (ACT_DLTA_HDR *) malloc( d );
1703 	if (dlta_hdr == 0) TheEnd1("QT rle: malloc failed");
1704 	act->data = (xaUBYTE *)dlta_hdr;
1705 	dlta_hdr->flags = ACT_SNGL_BUF | DLTA_DATA;
1706 	dlta_hdr->fpos = 0; dlta_hdr->fsize = size;
1707 	xin->Seek_FPos(xin,cur_off,0);
1708 	ret = xin->Read_Block(xin, dlta_hdr->data, size);
1709 	if (ret != size)
1710         { fprintf(stdout,"QT: video read err\n");
1711           if (qt_frame_cnt)	return(xaTRUE);
1712 	  else			return(xaFALSE); }
1713       }
1714       cur_off += size;
1715 
1716       if (qtv_init_duration)
1717       { xaLONG t_time, t_timelo; double ftime;
1718 
1719         ftime = (1000.0 * (double)(qtv_init_duration))
1720 					/ (double)(qtv_tk_timescale);
1721         t_time = (xaULONG)(ftime);
1722         ftime -= (double)(t_time);
1723         t_timelo = (xaULONG)(ftime * (double)(1<<24));
1724 	t_time   += qt->vid_time;
1725 	t_timelo += qt->vid_timelo;
1726 	while(t_timelo >= 1<<24) { t_timelo -= 1<<24; t_time++; }
1727 
1728 /* Some Quicktimes have two tracks. One chock full of video and one
1729  * with a single image and a duration of the entire clip.
1730  * Unfortunately, by the time XAnim is done with that image, it's
1731  * too late for the others.
1732  *
1733  * TODO: Need a routine to detect overlaps and shorten as necessary.
1734  *
1735  */
1736 /*TESTING*/
1737 /* if (t_time > 500) t_time = 0; */
1738 
1739         QT_Add_Frame(t_time,t_timelo,act);
1740         qtv_init_duration = 0;
1741       }
1742       else
1743 	QT_Add_Frame(qt->vid_time,qt->vid_timelo,act);
1744       dlta_hdr->xpos = dlta_hdr->ypos = 0;
1745       dlta_hdr->xsize = qt->imagex;
1746       dlta_hdr->ysize = qt->imagey;
1747       dlta_hdr->special = 0;
1748       if (qtv_codecs[tag].decoder)
1749       { dlta_hdr->extra = qtv_codecs[tag].dlta_extra;
1750 	dlta_hdr->delta = qtv_codecs[tag].decoder;
1751 	dlta_hdr->xapi_rev = qtv_codecs[tag].xapi_rev;
1752       }
1753       else
1754       {
1755 	if (unsupported_flag == xaFALSE) /* only output single warning */
1756 	{
1757 	  fprintf(stdout,
1758 		"QT: Sections of this movie use an unsupported Video Codec\n");
1759 	  fprintf(stdout," and are therefore NOT viewable.\n");
1760 	  unsupported_flag = xaTRUE;
1761         }
1762         act->type = ACT_NOP;
1763       }
1764       ACT_Setup_Delta(qt,act,dlta_hdr,xin);
1765       cur_samp++;
1766       if (cur_samp >= qtv_samp_num) break;
1767     } /* end of sample number */
1768     if (cur_samp >= qtv_samp_num) break;
1769   } /* end of chunk_offset loop */
1770   return(xaTRUE);
1771 }
1772 
1773 
1774 
1775 /*********************************************
1776  * Read and Parse Audio Codecs
1777  *
1778  **********/
QT_Read_Audio_STSD(xin,clen)1779 void QT_Read_Audio_STSD(xin,clen)
1780 XA_INPUT	*xin;
1781 xaLONG	clen;
1782 { xaULONG i,version,num,cur,sup;
1783   version	= xin->Read_MSB_U32(xin);
1784   num		= xin->Read_MSB_U32(xin);
1785   clen -= 8;
1786   DEBUG_LEVEL2 fprintf(stdout,"     ver = %x  num = %x\n", version,num);
1787   if (qts_codecs == 0)
1788   { qts_codec_num = num;
1789     qts_codecs = (QTS_CODEC_HDR *)malloc(qts_codec_num
1790 						* sizeof(QTS_CODEC_HDR));
1791     if (qts_codecs==0) TheEnd1("QT STSD: malloc err");
1792     cur = 0;
1793   }
1794   else
1795   { QTS_CODEC_HDR *tcodecs;
1796     tcodecs = (QTS_CODEC_HDR *)malloc((qts_codec_num + num)
1797 						* sizeof(QTS_CODEC_HDR));
1798     if (tcodecs==0) TheEnd1("QT STSD: malloc err");
1799     for(i=0;i<qts_codec_num;i++) tcodecs[i] = qts_codecs[i];
1800     cur = qts_codec_num;
1801     qts_codec_num += num;
1802     FREE(qts_codecs,0x9014);
1803     qts_codecs = tcodecs;
1804   }
1805   sup = 0;
1806   for(i=0; i < num; i++)
1807   {
1808     sup |= QT_Read_Audio_Codec_HDR( &qts_codecs[cur], xin, &clen );
1809     cur++;
1810   }
1811   if (sup == 0)
1812   {
1813     if (qt_audio_attempt == xaTRUE)
1814     {
1815       qt_audio_attempt = xaFALSE;
1816     }
1817   }
1818   else qt_audio_flag = 1;
1819 
1820 	/** If Extra bytes, skip over them **/
1821   if (clen)
1822   { DEBUG_LEVEL1 fprintf(stdout,"QT Audio STSD len mismatch %x\n",clen);
1823     xin->Seek_FPos(xin,clen,1);
1824   }
1825 }
1826 
1827 
QT_Read_Audio_Codec_HDR(c_hdr,xin,clen)1828 xaULONG QT_Read_Audio_Codec_HDR(c_hdr,xin, clen)
1829 QTS_CODEC_HDR	*c_hdr;
1830 XA_INPUT		*xin;
1831 xaLONG		*clen;
1832 { xaULONG len;
1833   xaULONG ret = 1;
1834   len			= xin->Read_MSB_U32(xin);
1835   c_hdr->format		= xin->Read_MSB_U32(xin);
1836   c_hdr->compression	= XA_AUDIO_INVALID;
1837   c_hdr->dref_id	= xin->Read_MSB_U32(xin);
1838   c_hdr->version	= xin->Read_MSB_U32(xin);
1839   c_hdr->codec_rev	= xin->Read_MSB_U32(xin);
1840   c_hdr->vendor		= xin->Read_MSB_U32(xin);
1841   c_hdr->chan_num	= xin->Read_MSB_U16(xin);
1842   c_hdr->bits_samp	= xin->Read_MSB_U16(xin);
1843 
1844 /* Some Mac Shareware program screws up when converting AVI's to QT's */
1845   if (   (c_hdr->bits_samp == 1)
1846       && (   (c_hdr->format == QT_twos)
1847           || (c_hdr->format == QT_sowt)
1848           || (c_hdr->format == QT_raw)
1849           || (c_hdr->format == QT_raw00)
1850      )  )                                       c_hdr->bits_samp = 8;
1851 
1852   c_hdr->comp_id	= xin->Read_MSB_U16(xin);
1853   c_hdr->pack_size	= xin->Read_MSB_U16(xin);
1854   c_hdr->samp_rate	= xin->Read_MSB_U16(xin);
1855   c_hdr->pad		= xin->Read_MSB_U16(xin);
1856 
1857   *clen -= 36;
1858 
1859   if (c_hdr->format == QT_twos) c_hdr->compression = XA_AUDIO_SIGNED;
1860   else if (c_hdr->format == QT_sowt) c_hdr->compression = XA_AUDIO_SIGNED;
1861   else if (c_hdr->format == QT_raw)
1862   { if (c_hdr->bits_samp==8)    c_hdr->compression = XA_AUDIO_LINEAR;
1863     else                        c_hdr->compression = XA_AUDIO_SIGNED;
1864   }
1865   else if (c_hdr->format == QT_raw00) c_hdr->compression = XA_AUDIO_LINEAR;
1866   else if (c_hdr->format == QT_ima4) c_hdr->compression = XA_AUDIO_IMA4;
1867   else if (c_hdr->format == QT_agsm) c_hdr->compression = XA_AUDIO_GSM;
1868   else if (c_hdr->format == QT_ulaw)
1869   {  c_hdr->compression = XA_AUDIO_ULAW;
1870      c_hdr->bits_samp = 8;  /* why they list it at 16 I have no clue */
1871   }
1872   else if (c_hdr->format == QT_MAC3)
1873   { fprintf(stdout,
1874 	"  Audio Codec: Apple MAC3 not yet supported.\n");
1875      ret = 0;
1876   }
1877   else if (c_hdr->format == QT_MAC6)
1878   { fprintf(stdout,
1879 	"  Audio Codec: Apple MAC6 not yet supported.\n");
1880      ret = 0;
1881   }
1882   else if (c_hdr->format == QT_QDMC)
1883   { fprintf(stdout,
1884 	"  Audio Codec: QDesign Music Codec (QDMC) not yet supported.\n");
1885      ret = 0;
1886   }
1887   else if (c_hdr->format == QT_Qclp)
1888   { fprintf(stdout,
1889 	"  Audio Codec: QualComm PureVoice (Qclp) not yet supported.\n");
1890      ret = 0;
1891   }
1892   else
1893   { xaULONG t = c_hdr->format;
1894     fprintf(stdout,"Unknown(and unsupported) Audio Codec: %c%c%c%c(0x%x).\n",
1895 		((t>>24) & 0x7f), ((t>>16) & 0x7f),
1896 		((t>>8) & 0x7f), (t & 0x7f),		 t);
1897     ret = 0;
1898   }
1899 
1900 /*** If not supported, then already output ***/
1901   if (ret & xa_verbose)
1902   {
1903     fprintf(stdout,"  Audio Codec: "); QT_Audio_Type(c_hdr->format);
1904     fprintf(stdout," Rate=%d Chans=%d Bps=%d\n",
1905 	c_hdr->samp_rate,c_hdr->chan_num,c_hdr->bits_samp);
1906   }
1907 
1908   if (c_hdr->bits_samp==8) c_hdr->bps = 1;
1909   else if (c_hdr->bits_samp==16) c_hdr->bps = 2;
1910   else if (c_hdr->bits_samp==32) c_hdr->bps = 4;
1911   else c_hdr->bps = 100 + c_hdr->bits_samp;
1912 
1913   if (c_hdr->bps > 2) ret = 0;
1914   if (c_hdr->chan_num > 2) ret = 0;
1915 
1916 /* This is only valid for PCM type samples */
1917   if ( (c_hdr->bps==2)  &&
1918 	 (   ((c_hdr->compression & XA_AUDIO_TYPE_MASK) == XA_AUDIO_LINEAR)
1919 	  || ((c_hdr->compression & XA_AUDIO_TYPE_MASK) == XA_AUDIO_SIGNED)
1920 	 )
1921      )
1922   {
1923     c_hdr->compression |= XA_AUDIO_BPS_2_MSK;
1924         /* QT is normally bigendian except for sowt which is little endian */
1925     if (c_hdr->format != QT_sowt) c_hdr->compression |= XA_AUDIO_BIGEND_MSK;
1926 
1927   }
1928   if (c_hdr->chan_num==2)
1929   {
1930     c_hdr->compression |= XA_AUDIO_STEREO_MSK;
1931     c_hdr->bps *= 2;
1932   }
1933 
1934   return(ret);
1935 }
1936 
QT_Audio_Type(type)1937 void QT_Audio_Type(type)
1938 xaULONG type;
1939 { switch(type)
1940   { case QT_raw:	fprintf(stdout,"PCM"); break;
1941     case QT_raw00:	fprintf(stdout,"PCM0"); break;
1942     case QT_twos:	fprintf(stdout,"TWOS"); break;
1943     case QT_MAC3:	fprintf(stdout,"MAC3"); break;
1944     case QT_MAC6:	fprintf(stdout,"MAC6"); break;
1945     case QT_ima4:	fprintf(stdout,"IMA4"); break;
1946     case QT_ulaw:	fprintf(stdout,"uLaw"); break;
1947     default:		fprintf(stdout,"(%c%c%c%c)(%08x)",
1948 			  (char)((type>>24)&0xff), (char)((type>>16)&0xff),
1949 			  (char)((type>>8)&0xff),(char)((type)&0xff),type);
1950 	break;
1951   }
1952 }
1953 
1954 /**************
1955  *
1956  *
1957  *******/
QT_Read_Audio_Data(qt,xin,anim_hdr)1958 xaULONG QT_Read_Audio_Data(qt,xin,anim_hdr)
1959 XA_ANIM_SETUP *qt;
1960 XA_INPUT *xin;
1961 XA_ANIM_HDR *anim_hdr;
1962 {
1963   xaULONG ret,i;
1964   xaULONG cur_s2chunk,nxt_s2chunk;
1965   xaULONG tag;
1966 
1967 DEBUG_LEVEL1 fprintf(stdout,"QT_Read_Audio: attempt %x co# %d\n",
1968 				qt_audio_attempt,qts_chunkoff_num);
1969 
1970   cur_s2chunk	= 0;
1971   nxt_s2chunk	= qts_s2chunks[cur_s2chunk + 1].first;
1972   tag		= qts_s2chunks[cur_s2chunk].tag;
1973   qt_audio_freq	 = qts_codecs[tag].samp_rate;
1974   qt_audio_chans = qts_codecs[tag].chan_num;
1975   qt_audio_bps	 = qts_codecs[tag].bps;
1976   qt_audio_type	 = qts_codecs[tag].compression;
1977   qt_audio_end	 = 1;
1978 
1979   /* Initial Silence if any. PODNOTE: Eventually Modify for Middle silence */
1980   /**** TODO: detect middle silences and add NOP audio chunks ****/
1981   qts_init_duration += qtv_start_offset;
1982   if (qts_init_duration)
1983   { xaULONG snd_size;
1984 
1985     snd_size = (qt_audio_freq * qts_init_duration) / qts_tk_timescale;
1986     if (XA_Add_Sound(anim_hdr,0,XA_AUDIO_NOP, -1, qt_audio_freq,
1987 	snd_size, &qt->aud_time, &qt->aud_timelo, 0, 0) == xaFALSE)
1988 							return(xaFALSE);
1989   }
1990 
1991 
1992   /* Loop through chunk offsets */
1993   for(i=0; i < qts_chunkoff_num; i++)
1994   { xaULONG size,chunk_off,num_samps,snd_size;
1995     xaULONG blockalign, sampsblock;
1996 
1997     if ( (i == nxt_s2chunk) && ((cur_s2chunk+1) < qts_s2chunk_num) )
1998     {
1999       cur_s2chunk++;
2000       nxt_s2chunk = qts_s2chunks[cur_s2chunk+1].first;
2001     }
2002     num_samps = qts_s2chunks[cur_s2chunk].num; /* * sttz */
2003 
2004     /* Check tags and possibly move to new codec */
2005     if (qts_s2chunks[cur_s2chunk].tag >= qts_codec_num)
2006     {
2007       fprintf(stdout,"QT Data: Warning stsc chunk invalid %d tag %d\n",
2008 		cur_s2chunk,qts_s2chunks[cur_s2chunk].tag);
2009     }
2010     else if (qts_s2chunks[cur_s2chunk].tag != tag)
2011     {
2012       tag =  qts_s2chunks[cur_s2chunk].tag;
2013       qt_audio_freq  = qts_codecs[tag].samp_rate;
2014       qt_audio_chans = qts_codecs[tag].chan_num;
2015       qt_audio_bps   = qts_codecs[tag].bps;
2016       qt_audio_type  = qts_codecs[tag].compression;
2017       qt_audio_end   = 1;
2018     }
2019 
2020 /* NOTE: THE STSZ CHUNKS FOR AUDIO IS TOTALLY F****D UP AND INCONSISTENT
2021  * ACROSS MANY ANIMATIONS. CURRENTLY JUST IGNORE THIS. */
2022     if (i < qts_samp_num) size = qts_samp_sizes[i];
2023     else if (qts_samp_num) size = qts_samp_sizes[qts_samp_num-1];
2024     else size = qt_audio_bps;
2025 
2026     if (size > qt_audio_bps)
2027     {
2028 	fprintf(stdout,"QT UNIQE AUDIO: sz %d bps %d\n",size,qt_audio_bps);
2029     }
2030 
2031     chunk_off =  qts_chunkoffs[i];
2032 
2033 
2034 /*
2035 fprintf(stdout,"SND: off %08x size %08x\n",chunk_off, size);
2036 */
2037     if (qt_audio_type == XA_AUDIO_IMA4_M)
2038     { xaULONG numblks = num_samps / 0x40;
2039       snd_size = numblks * 0x22;
2040       blockalign = 0x22;
2041       sampsblock = 0x40;
2042     }
2043     else if (qt_audio_type == XA_AUDIO_IMA4_S)
2044     { xaULONG numblks = num_samps / 0x40;
2045       snd_size = numblks * 0x44;
2046       blockalign = 0x44;
2047       sampsblock = 0x40;
2048     }
2049     else if (qt_audio_type == XA_AUDIO_GSM_M)
2050     { xaULONG numblks = num_samps / 160;
2051       snd_size = numblks * 33;
2052       blockalign = 33;
2053       sampsblock = 160;
2054     }
2055     else
2056     { snd_size = num_samps * qt_audio_bps;
2057       blockalign = qt_audio_bps; /* not really valid yet */
2058       sampsblock = 0x1;
2059     }
2060 
2061 DEBUG_LEVEL1 fprintf(stdout,"snd_size %x  numsamps %x size %x bps %d off %x\n",
2062 		snd_size,num_samps,size,qt_audio_bps,chunk_off);
2063 
2064     if (xa_file_flag == xaTRUE)
2065     {
2066       if (XA_Add_Sound(anim_hdr,0,qt_audio_type, chunk_off, qt_audio_freq,
2067 		snd_size, &qt->aud_time, &qt->aud_timelo,
2068 		blockalign,sampsblock) == xaFALSE) return(xaFALSE);
2069       if (snd_size > qt->max_faud_size) qt->max_faud_size = snd_size;
2070     }
2071     else
2072     { xaUBYTE *snd_data = (xaUBYTE *)malloc(snd_size);
2073       if (snd_data==0) TheEnd1("QT aud_dat: malloc err");
2074       xin->Seek_FPos(xin,chunk_off,0);  /* move to start of chunk data */
2075       ret = xin->Read_Block(xin, snd_data, snd_size);
2076       if (ret != snd_size)
2077       { fprintf(stdout,"QT: snd rd err\n");
2078         return(xaTRUE);
2079       }
2080       if (XA_Add_Sound(anim_hdr,snd_data,qt_audio_type, -1, qt_audio_freq,
2081 		snd_size, &qt->aud_time, &qt->aud_timelo,
2082 		blockalign,sampsblock) == xaFALSE) return(xaFALSE);
2083 
2084     }
2085   } /* end of chunk_offset loop */
2086   return(xaTRUE);
2087 }
2088 
2089 
2090 /********
2091  * Have No Clue
2092  *
2093  ****/
QT_Read_STGS(xin,len)2094 void QT_Read_STGS(xin,len)
2095 XA_INPUT *xin;
2096 xaLONG len;
2097 {
2098   xaULONG i,version,num;
2099   xaULONG samps,pad;
2100 
2101   version	= xin->Read_MSB_U32(xin);
2102   num		= xin->Read_MSB_U32(xin); len -= 16;
2103   qt_stgs_num = 0;
2104   for(i=0; i<num; i++)
2105   {
2106     samps	= xin->Read_MSB_U32(xin);
2107     pad		= xin->Read_MSB_U32(xin);	len -= 8;
2108     qt_stgs_num += samps;
2109   }
2110   while(len > 0) {len--; xin->Read_U8(xin); }
2111 }
2112 
2113 int qt_2map[] = {
2114 0x93, 0x65, 0x5e,
2115 0xff, 0xff, 0xff,
2116 0xdf, 0xd0, 0xab,
2117 0x00, 0x00, 0x00
2118 };
2119 
2120 /* MAX */
2121 int qt_4map[] = {
2122 0xff, 0xfb, 0xff,
2123 0xef, 0xd9, 0xbb,
2124 0xe8, 0xc9, 0xb1,
2125 0x93, 0x65, 0x5e,
2126 0xfc, 0xde, 0xe8,
2127 0x9d, 0x88, 0x91,
2128 0xff, 0xff, 0xff,
2129 0xff, 0xff, 0xff,
2130 0xff, 0xff, 0xff,
2131 0x47, 0x48, 0x37,
2132 0x7a, 0x5e, 0x55,
2133 0xdf, 0xd0, 0xab,
2134 0xff, 0xfb, 0xf9,
2135 0xe8, 0xca, 0xc5,
2136 0x8a, 0x7c, 0x77,
2137 0x00, 0x00, 0x00
2138 };
2139 
2140 
2141 /**************************************
2142  * QT_Create_Default_Cmap
2143  *
2144  * This routine recreates the Default Apple colormap.
2145  * It is an educated quess after looking at two quicktime animations
2146  * and may not be totally correct, but seems to work okay.
2147  */
QT_Create_Default_Cmap(cmap,cnum)2148 void QT_Create_Default_Cmap(cmap,cnum)
2149 ColorReg *cmap;
2150 xaULONG cnum;
2151 {
2152   xaLONG r,g,b,i;
2153 
2154   if (cnum == 4)
2155   {
2156     for(i=0;i<4;i++)
2157     { int d = i * 3;
2158       cmap[i].red   = 0x101 * qt_2map[d];
2159       cmap[i].green = 0x101 * qt_2map[d+1];
2160       cmap[i].blue  = 0x101 * qt_2map[d+2];
2161     }
2162   }
2163   else if (cnum == 16)
2164   {
2165     for(i=0;i<16;i++)
2166     { int d = i * 3;
2167       cmap[i].red   = 0x101 * qt_4map[d];
2168       cmap[i].green = 0x101 * qt_4map[d+1];
2169       cmap[i].blue  = 0x101 * qt_4map[d+2];
2170     }
2171   }
2172   else
2173   { static xaUBYTE pat[10] = {0xee,0xdd,0xbb,0xaa,0x88,0x77,0x55,0x44,0x22,0x11};
2174     r = g = b = 0xff;
2175     for(i=0;i<215;i++)
2176     {
2177       cmap[i].red   = 0x101 * r;
2178       cmap[i].green = 0x101 * g;
2179       cmap[i].blue  = 0x101 * b;
2180       b -= 0x33;
2181       if (b < 0) { b = 0xff; g -= 0x33; if (g < 0) { g = 0xff; r -= 0x33; } }
2182     }
2183     for(i=0;i<10;i++)
2184     { xaULONG d = 0x101 * pat[i];
2185       xaULONG ip = 215 + i;
2186       cmap[ip].red   = d; cmap[ip].green = cmap[ip].blue  = 0; ip += 10;
2187       cmap[ip].green = d; cmap[ip].red   = cmap[ip].blue  = 0; ip += 10;
2188       cmap[ip].blue  = d; cmap[ip].red   = cmap[ip].green = 0; ip += 10;
2189       cmap[ip].red   = cmap[ip].green = cmap[ip].blue  = d;
2190     }
2191     cmap[255].red = cmap[255].green = cmap[255].blue  = 0x00;
2192   }
2193 }
2194 
2195 
2196 /**************************************
2197  * QT_Create_Gray_Cmap
2198  *
2199  * This routine recreates the Default Gray Apple colormap.
2200  */
QT_Create_Gray_Cmap(cmap,flag,num)2201 void QT_Create_Gray_Cmap(cmap,flag,num)
2202 ColorReg *cmap;
2203 xaULONG flag;	/* flag=0  0=>255;  flag=1 255=>0 */
2204 xaULONG num;	/* size of color map */
2205 {
2206   xaLONG g,i;
2207 
2208   if (num == 256)
2209   {
2210     g = (flag)?(0x00):(0xff);
2211     for(i=0;i<256;i++)
2212     {
2213       cmap[i].red   = 0x101 * g;
2214       cmap[i].green = 0x101 * g;
2215       cmap[i].blue  = 0x101 * g;
2216       cmap[i].gray  = 0x101 * g;
2217       if (flag) g++; else g--;
2218     }
2219   }
2220   else if (num == 16)
2221   {
2222     g = 0xf;
2223     for(i=0;i<16;i++)
2224     {
2225       cmap[i].red   = 0x1111 * g;
2226       cmap[i].green = 0x1111 * g;
2227       cmap[i].blue  = 0x1111 * g;
2228       cmap[i].gray  = 0x1111 * g;
2229       g--;
2230     }
2231   }
2232 }
2233 
2234 
2235 
2236