home *** CD-ROM | disk | FTP | other *** search
/ Dream 44 / Amiga_Dream_44.iso / Linux / Apps / xanim.tgz / xanim / xanim27064 / xa_qt.c < prev    next >
C/C++ Source or Header  |  1997-01-26  |  61KB  |  2,102 lines

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