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