home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 44
/
Amiga_Dream_44.iso
/
Linux
/
Apps
/
xanim.tgz
/
xanim
/
xanim27064
/
xa_qt.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-01-26
|
61KB
|
2,102 lines
/*
* xa_qt.c
*
* Copyright (C) 1993,1994,1995,1996,1997 by Mark Podlipec.
* All rights reserved.
*
* This software may be freely copied, modified and redistributed without
* fee for non-commerical purposes provided that this copyright notice is
* preserved intact on all copies and modified copies.
*
* There is no warranty or other guarantee of fitness of this software.
* It is provided solely "as is". The author(s) disclaim(s) all
* responsibility and liability with respect to this software's usage
* or its effect upon hardware or computer systems.
*
*/
/* REVISIONS ***********
* 31Aug94 RPZA was using *iptr+=row_inc instead of iptr+=row_inc.
* 15Sep94 Added support for RAW32 format. straight RGB with 0x00 up front.
* 19Sep94 Fixed stereo audio bug. Needed to double bps with stereo snd.
* 20Sep94 I forgot to declare fin in the QT_Read_Audio_STSD(fin) and
* that caused problems on the Alpha machines.
* 20Sep94 Added RAW4,RAW16,RAW24,RAW32,Gray CVID and Gray Other codecs.
* 07Nov94 Fixed bug in RLE,RLE16,RLE24,RLE32 and RLE1 code, where I
* had improperly guessed what a header meant. Now it's a different
* hopeful more correct guess.
* 29Dec94 Above bug wasn't fixe in RLE(8bit), now it is.
* 30Jan95 Appletalk on SONY uses directory .afprsrc for resource forks
* instead of .resource like other programs use.
* patch written by Kazushi Yoshida.
* 11Feb95 Fixed Bug with RLE depth 1 codec.
* 04Mar95 Added Dithering(+F option) to Cinepak Video Codec.
* 08Mar95 Fixed audio Bug with SGI generated quicktimes audio depth > 8.
* 17Mar95 Fixed bug that was causing quicktime to erroneously send
* back a FULL_IM flag allowing serious skipping to occur. This
* causes on screen corruption if the Video Codec doesn't
* really support serious skipping.
* 11Apr95 Fixed bug in QT_Create_Gray_Cmap that caused last color of
* colormap not to be generated correctly. Only affected
* the Gray Quicktime codecs.
* 16Jun95 Removed Cinepak Codec per Radius request.
* 15Sep95 Code snippet to support erroneous Quicktime files that
* have the length of the "mdat" atom, but not the "mdat" ID.
* 15Sep95 Better check for truncated Quicktime files
* 26Feb96 Fixed prob in Read_Video_Data, where timing chunks were
* incremented properly resulting in video/audio sync problems.
* 1Mar96 Moved Video Codecs into xa_qt_decs.c file
* 19Mar96 Modified for support of audio only files.
*/
#include "xa_qt.h"
#include "xa_codecs.h"
#include <sys/stat.h>
static XA_CODEC_HDR qt_codec_hdr;
/******************** Radius Cinepak External Library XAnim funtions ********/
#ifdef XA_CINEPAK
extern xaULONG Cinepak_What_Rev_API();
extern xaLONG Cinepak_Codec_Query();
#define XA_CINEPAK_QUERY_CNT 1
#else
#define XA_CINEPAK_QUERY_CNT 0
#endif
/******************** Intel Indeo External Library XAnim funtions ***********/
#ifdef XA_INDEO
extern xaULONG Indeo_What_Rev_API();
extern xaLONG Indeo_Codec_Query();
#define XA_INDEO_QUERY_CNT 1
#else
#define XA_INDEO_QUERY_CNT 0
#endif
/******************** Kodak Photo CD External Library XAnim funtions *********/
#ifdef XA_KPCD
extern xaULONG KPCD_What_Rev_API();
extern xaLONG KPCD_Codec_Query();
#define XA_KPCD_QUERY_CNT 1
#else
#define XA_KPCD_QUERY_CNT 0
#endif
extern xaLONG QT_Codec_Query();
extern xaLONG QT_UNK_Codec_Query();
#define QT_QUERY_CNT 2 + XA_INDEO_QUERY_CNT + XA_CINEPAK_QUERY_CNT \
+ XA_KPCD_QUERY_CNT
xaLONG (*qt_query_func[])() = {
#ifdef XA_INDEO
Indeo_Codec_Query,
#endif
#ifdef XA_CINEPAK
Cinepak_Codec_Query,
#endif
#ifdef XA_KPCD
KPCD_Codec_Query,
#endif
QT_Codec_Query,
QT_UNK_Codec_Query};
xaULONG QT_Read_Video_Codec_HDR();
xaULONG QT_Read_Audio_Codec_HDR();
void QT_Audio_Type();
xaULONG QT_Read_File();
void QT_Create_Default_Cmap();
void QT_Create_Gray_Cmap();
extern char *XA_rindex();
void CMAP_Cache_Clear();
void CMAP_Cache_Init();
xaUSHORT qt_gamma_adj[32];
QTV_CODEC_HDR *qtv_codecs;
QTS_CODEC_HDR *qts_codecs;
xaULONG qtv_codec_num,qts_codec_num;
XA_ACTION *ACT_Get_Action();
XA_CHDR *ACT_Get_CMAP();
XA_CHDR *CMAP_Create_332();
XA_CHDR *CMAP_Create_422();
XA_CHDR *CMAP_Create_Gray();
void ACT_Add_CHDR_To_Action();
void ACT_Setup_Mapped();
XA_CHDR *CMAP_Create_CHDR_From_True();
xaUBYTE *UTIL_RGB_To_FS_Map();
xaUBYTE *UTIL_RGB_To_Map();
xaULONG CMAP_Find_Closest();
xaULONG UTIL_Get_MSB_Long();
xaLONG UTIL_Get_MSB_Short();
xaULONG UTIL_Get_MSB_UShort();
extern XA_ANIM_SETUP *XA_Get_Anim_Setup();
extern ACT_Setup_DeltaOLD();
void XA_Free_Anim_Setup();
FILE *QT_Open_File();
xaULONG QT_Parse_Chunks();
xaULONG QT_Parse_Bin();
xaULONG QT_Read_Video_Data();
xaULONG QT_Read_Audio_Data();
void QT_Print_ID();
void QT_Read_MVHD();
void QT_Read_TKHD();
void QT_Read_ELST();
void QT_Read_MDHD();
void QT_Read_HDLR();
xaULONG QT_Read_Video_STSD();
void QT_Read_Audio_STSD();
void QT_Read_Name();
void QT_Read_STTS();
void QT_Read_STSS();
void QT_Read_STCO();
void QT_Read_STSZ();
void QT_Read_STSC();
void QT_Read_STGS();
void QT_Free_Stuff();
void QT_Codec_List();
QT_MVHDR qt_mvhdr;
QT_TKHDR qt_tkhdr;
QT_MDHDR qt_mdhdr;
QT_HDLR_HDR qt_hdlr_hdr;
char qt_rfilename[256];
char qt_dfilename[256];
static xaULONG qt_video_flag;
static xaULONG qt_data_flag;
static xaULONG qt_v_flag, qt_s_flag;
static xaULONG qt_moov_flag;
static xaULONG qt_frame_cnt;
static xaULONG qt_mv_timescale,qt_md_timescale;
static xaULONG qt_vid_timescale, qt_aud_timescale;
static xaULONG qt_tk_timescale,qts_tk_timescale,qtv_tk_timescale;
#define QT_CODEC_UNK 0x000
/*** SOUND SUPPORT ****/
static xaULONG qt_audio_attempt;
static xaULONG qt_audio_type;
static xaULONG qt_audio_freq;
static xaULONG qt_audio_chans;
static xaULONG qt_audio_bps;
static xaULONG qt_audio_end;
xaULONG XA_Add_Sound();
QT_FRAME *qt_frame_start,*qt_frame_cur;
QT_FRAME *QT_Add_Frame(time,timelo,act)
xaULONG time,timelo;
XA_ACTION *act;
{
QT_FRAME *fframe;
fframe = (QT_FRAME *) malloc(sizeof(QT_FRAME));
if (fframe == 0) TheEnd1("QT_Add_Frame: malloc err");
fframe->time = time;
fframe->timelo = timelo;
fframe->act = act;
fframe->next = 0;
if (qt_frame_start == 0) qt_frame_start = fframe;
else qt_frame_cur->next = fframe;
qt_frame_cur = fframe;
qt_frame_cnt++;
return(fframe);
}
void QT_Free_Frame_List(fframes)
QT_FRAME *fframes;
{
QT_FRAME *ftmp;
while(fframes != 0)
{
ftmp = fframes;
fframes = fframes->next;
FREE(ftmp,0x9000);
}
}
xaLONG Is_QT_File(filename)
char *filename;
{
FILE *fin;
xaULONG ret;
if ( (fin=QT_Open_File(filename,qt_rfilename,qt_dfilename)) == 0)
return(xaNOFILE);
ret = QT_Parse_Bin(fin);
fclose(fin);
if ( ret != 0 ) return(xaTRUE);
return(xaFALSE);
}
/* FOR PARSING Quicktime Files */
xaULONG *qtv_samp_sizes,*qts_samp_sizes;
xaULONG qtv_samp_num,qts_samp_num;
xaULONG qt_init_duration,qts_init_duration, qtv_init_duration;
xaULONG qt_start_offset,qts_start_offset, qtv_start_offset;
QT_S2CHUNK_HDR *qtv_s2chunks,*qts_s2chunks;
xaULONG qtv_s2chunk_num,qts_s2chunk_num;
QT_T2SAMP_HDR *qtv_t2samps,*qts_t2samps;
xaULONG qtv_t2samp_num,qts_t2samp_num;
xaULONG qtv_chunkoff_num,qts_chunkoff_num;
xaULONG *qtv_chunkoffs,*qts_chunkoffs;
xaULONG qtv_codec_lstnum,qts_codec_lstnum;
xaULONG qtv_chunkoff_lstnum,qts_chunkoff_lstnum;
xaULONG qtv_samp_lstnum,qts_samp_lstnum;
xaULONG qtv_s2chunk_lstnum,qts_s2chunk_lstnum;
xaULONG qt_stgs_num;
xaULONG qt_has_ctab;
/* main() */
xaULONG QT_Read_File(fname,anim_hdr,audio_attempt)
char *fname;
XA_ANIM_HDR *anim_hdr;
xaULONG audio_attempt; /* xaTRUE is audio is to be attempted */
{ /* XA_INPUT *xin = anim_hdr->xin; */
FILE *fin;
xaLONG i,t_time;
xaULONG t_timelo;
XA_ANIM_SETUP *qt;
xaULONG qt_has_audio, qt_has_video;
qt = XA_Get_Anim_Setup();
qt->vid_time = XA_GET_TIME( 100 ); /* default 10 fps */
qt->compression = QT_CODEC_UNK;
qt_has_audio = xaFALSE;
qt_has_video = xaFALSE;
qt_has_ctab = xaFALSE;
qt_stgs_num = 0;
qtv_codec_lstnum = qts_codec_lstnum = 0;
qtv_chunkoff_lstnum = qts_chunkoff_lstnum = 0;
qtv_samp_lstnum = qts_samp_lstnum = 0;
qtv_codecs = 0;
qts_codecs = 0;
qtv_codec_num = qts_codec_num = 0;
qt_data_flag = xaFALSE;
qt_video_flag = 0;
qt_v_flag = qt_s_flag = 0;
qt_moov_flag = xaFALSE;
qt_frame_cnt = 0;
qt_frame_start = 0;
qt_frame_cur = 0;
qt_vid_timescale = qt_aud_timescale = 1000;
qt_mv_timescale = qt_md_timescale = 1000;
qts_tk_timescale = qtv_tk_timescale = 1000;
qtv_chunkoff_num = qts_chunkoff_num = 0;
qtv_chunkoffs = qts_chunkoffs = 0;
qtv_s2chunk_num = qts_s2chunk_lstnum = 0;
qtv_s2chunks = qts_s2chunks = 0;
qtv_s2chunk_num = qts_s2chunk_lstnum = 0;
qtv_t2samp_num = qts_t2samp_num = 0;
qtv_t2samps = qts_t2samps = 0;
qtv_samp_sizes = qts_samp_sizes = 0;
qtv_samp_num = qts_samp_num = 0;
qt_init_duration = qts_init_duration = qtv_init_duration = 0;
qt_start_offset = qts_start_offset = qtv_start_offset = 0;
qt_audio_attempt = audio_attempt;
for(i=0;i<32;i++) qt_gamma_adj[i] = xa_gamma_adj[ ((i<<3)|(i>>2)) ];
if ( (fin=QT_Open_File(fname,qt_rfilename,qt_dfilename)) == 0)
{
fprintf(stdout,"QT_Read: can't open %s\n",qt_rfilename);
XA_Free_Anim_Setup(qt);
return(xaFALSE);
}
if ( QT_Parse_Bin(fin) == 0 )
{
fprintf(stdout,"Not quicktime file\n");
XA_Free_Anim_Setup(qt);
return(xaFALSE);
}
if (QT_Parse_Chunks(anim_hdr,qt,fin) == xaFALSE)
{
QT_Free_Stuff();
XA_Free_Anim_Setup(qt);
return(xaFALSE);
}
if (qt_data_flag == xaFALSE)
{ /* mdat was not in .rscr file need to open .data file */
fclose(fin); /* close .rscr file */
if (qt_dfilename[0] == 0)
{ fprintf(stdout,"QT_Data: No data in %s file. Can't find .data file.\n",
qt_rfilename);
return(xaFALSE);
}
if ( (fin=fopen(qt_dfilename,XA_OPEN_MODE)) == 0)
{ fprintf(stdout,"QT_Data: can't open %s file.\n",qt_dfilename);
return(xaFALSE);
}
} else strcpy(qt_dfilename,qt_rfilename); /* r file is d file */
DEBUG_LEVEL1 fprintf(stdout,"reading data\n");
if (qtv_samp_sizes) qt_has_video = QT_Read_Video_Data(qt,fin,anim_hdr);
if ((qts_samp_sizes) && (qt_audio_attempt==xaTRUE))
qt_has_audio = QT_Read_Audio_Data(qt,fin,anim_hdr);
fclose(fin);
if ((qt_has_video == xaFALSE) || (qt_frame_cnt == 0))
{
if (qt_has_audio == xaFALSE) /* no video and no audio */
{ if (qt_moov_flag==xaTRUE)
{
if (qt_audio_attempt == xaFALSE)
{
fprintf(stdout,"QT: no video to play. possibly truncated.\n");
}
else fprintf(stdout,"QT: no video/audio to play. possibly truncated.\n");
}
else
fprintf(stdout,"QT: file possibly truncated or missing .rsrc info.\n");
return(xaFALSE);
}
if (qtv_samp_sizes)
fprintf(stdout,"QT Notice: No supported Video frames - treating as audio only file\n");
anim_hdr->total_time = (qt_mvhdr.duration * 1000) / (qt_mvhdr.timescale);
}
else
{
anim_hdr->frame_lst = (XA_FRAME *)
malloc( sizeof(XA_FRAME) * (qt_frame_cnt+1));
if (anim_hdr->frame_lst == NULL) TheEnd1("QT_Read_File: frame malloc err");
qt_frame_cur = qt_frame_start;
i = 0;
t_time = 0;
t_timelo = 0;
while(qt_frame_cur != 0)
{ if (i >= qt_frame_cnt)
{ fprintf(stdout,"QT_Read_Anim: frame inconsistency %d %d\n",
i,qt_frame_cnt); break;
}
anim_hdr->frame_lst[i].time_dur = qt_frame_cur->time;
anim_hdr->frame_lst[i].zztime = t_time;
t_time += qt_frame_cur->time;
t_timelo += qt_frame_cur->timelo;
while(t_timelo >= (1<<24)) {t_time++; t_timelo -= (1<<24);}
anim_hdr->frame_lst[i].act = qt_frame_cur->act;
qt_frame_cur = qt_frame_cur->next;
i++;
}
if (i > 0)
{ anim_hdr->last_frame = i - 1;
anim_hdr->total_time = anim_hdr->frame_lst[i-1].zztime
+ anim_hdr->frame_lst[i-1].time_dur;
}
else { anim_hdr->last_frame = 0; anim_hdr->total_time = 0; }
if (xa_verbose)
{ fprintf(stdout, " Frame Stats: Size=%dx%d Frames=%d",
qt->imagex,qt->imagey,qt_frame_cnt);
if (anim_hdr->total_time)
{ float fps = (float)(1000 * qt_frame_cnt)/(float)(anim_hdr->total_time);
fprintf(stdout, " avfps=%2.1f\n",fps);
}
else fprintf(stdout,"\n");
}
anim_hdr->imagex = qt->max_imagex;
anim_hdr->imagey = qt->max_imagey;
anim_hdr->imagec = qt->imagec;
anim_hdr->imaged = 8; /* nop */
anim_hdr->frame_lst[i].time_dur = 0;
anim_hdr->frame_lst[i].zztime = -1;
anim_hdr->frame_lst[i].act = 0;
anim_hdr->loop_frame = 0;
}
if (xa_buffer_flag == xaFALSE) anim_hdr->anim_flags |= ANIM_SNG_BUF;
anim_hdr->max_fvid_size = qt->max_fvid_size;
anim_hdr->max_faud_size = qt->max_faud_size;
if (xa_file_flag == xaTRUE)
{ xaULONG len;
anim_hdr->anim_flags |= ANIM_USE_FILE;
len = strlen(qt_dfilename) + 1;
anim_hdr->fname = (char *)malloc(len);
if (anim_hdr->fname==0) TheEnd1("QT: malloc fname err");
strcpy(anim_hdr->fname,qt_dfilename);
}
QT_Free_Stuff();
XA_Free_Anim_Setup(qt);
return(xaTRUE);
}
void QT_Free_Stuff()
{
QT_Free_Frame_List(qt_frame_start);
if (qtv_samp_sizes) FREE(qtv_samp_sizes,0x9003);
if (qts_samp_sizes) FREE(qts_samp_sizes,0x9004);
if (qtv_codecs) FREE(qtv_codecs,0x9005);
if (qts_codecs) FREE(qts_codecs,0x9006);
if (qtv_t2samps) FREE(qtv_t2samps,0x9007);
if (qts_t2samps) FREE(qts_t2samps,0x9008);
if (qtv_s2chunks) FREE(qtv_s2chunks,0x9009);
if (qts_s2chunks) FREE(qts_s2chunks,0x900a);
if (qtv_chunkoffs) FREE(qtv_chunkoffs,0x900b);
if (qts_chunkoffs) FREE(qts_chunkoffs,0x900c);
}
FILE *QT_Open_File(fname,r_file,d_file)
char *fname,*r_file,*d_file;
{ FILE *fin;
struct stat sb;
/* check to see if fname exists? */
if ( (fin=fopen(fname,XA_OPEN_MODE)) != 0) /* filename is as give */
{ /*three choices - with or without .rsrc ending, or using .resource subdir*/
xaLONG len;
FILE *ftst;
/* path/fname exits. */
/* check for path/.resource/fname */
{
char *lastdirsep;
strcpy(r_file,fname); /* copy path/fname to r */
lastdirsep = XA_rindex(r_file, '/'); /* find sep if any */
if ( lastdirsep != (char *)(NULL) )
{
strcpy(d_file,lastdirsep); /* save fname to d*/
lastdirsep++; *lastdirsep = 0; /* cut of fname off r*/
/*POD NOTE: eventually might want to check for both, but for now
* let's just wait and see. */
#ifdef sony
/* For AppleTalk of NEWS-OS, .rsrc file is in .afprsrc directory */
strcat(lastdirsep, ".afprsrc/"); /* add .afprsrc to r*/
#else
strcat(lastdirsep, ".resource/"); /* add .resource to r*/
#endif
strcat(r_file, d_file); /* add fname to r */
}
else /* no path */
{
#ifdef sony
strcpy(r_file,".afprsrc/");
#else
strcpy(r_file,".resource/");
#endif
strcat(r_file,fname);
}
if ((stat(r_file,&sb) == 0) && (sb.st_size > 0))
{ if ( (ftst=fopen(r_file,"r")) != 0)
{ /* path/fname and path/.resource/fname exist - wrap it up */
strcpy(d_file,fname); /* setup .data name */
fclose(fin); /* close .data fork */
return(ftst); /* return .rsrc fork (in .resource) */
}
}
}
/* Now check for .rsrc or .data endings */
strcpy(r_file,fname);
strcpy(d_file,fname);
len = strlen(r_file) - 5;
if (len > 0)
{ char *tmp;
tmp = XA_rindex(d_file, '.'); /* get last "." */
if ( tmp == (char *)(NULL) ) { *d_file = 0; return(fin); }
else if (strcmp(tmp,".rsrc")==0) /* fname has .rsrc ending */
{
strcpy(tmp,".data"); /* overwrite .rsrc with .data in d*/
return(fin);
}
else if (strcmp(tmp,".data")==0) /* fname has .data ending */
{
strcpy(tmp,".rsrc"); /* overwrite .rsrc with .data in d*/
if ( (ftst=fopen(d_file,"r")) != 0) /* see if .rsrc exists */
{
char t_file[256]; /* swap r and d files */
strcpy(t_file,r_file); strcpy(r_file,d_file); strcpy(d_file,t_file);
fclose(fin); /* close .data file */
return(ftst); /* return .rsrc file */
}
/* hopefully .data is flattened. find out later */
else { *d_file = 0; return(fin); }
}
else { *d_file = 0; return(fin); }
}
else { *d_file = 0; return(fin); }
}
/* does fname.rsrc exist? */
strcpy(r_file,fname);
strcat(r_file,".rsrc");
if ( (fin=fopen(r_file,XA_OPEN_MODE)) != 0) /* fname.rsrc */
{ FILE *ftst;
/* if so, check .data existence */
strcpy(d_file,fname);
strcat(d_file,".data");
if ( (ftst=fopen(d_file,XA_OPEN_MODE)) != 0) fclose(ftst);
else *d_file = 0;
return(fin);
} else *d_file = 0;
return(0);
}
xaULONG QT_Parse_Chunks(anim_hdr,qt,fin)
XA_ANIM_HDR *anim_hdr;
XA_ANIM_SETUP *qt;
FILE *fin;
{
xaLONG file_len;
xaULONG id,len;
file_len = 1;
while(file_len > 0)
{
len = UTIL_Get_MSB_Long(fin);
id = UTIL_Get_MSB_Long(fin);
if ( (len == 0) && (id == QT_mdat) )
{
fprintf(stdout,"QT: mdat len is 0. You also need a .rsrc file.\n");
return(xaFALSE);
}
if (len < 8) { file_len = 0; continue; } /* just bad - finish this */
if (file_len == 1)
{
if (id == QT_moov) file_len = len + 8;
else file_len = len + 8;
}
DEBUG_LEVEL2 fprintf(stdout,"%c%c%c%c %04x len = %x file_len = %x\n",
(char)(id >> 24),(char)((id>>16)&0xff),
(char)((id>>8)&0xff),(char)(id&0xff),id,len,file_len);
switch(id)
{
/*--------------ATOMS------------------*/
case QT_trak:
qt_v_flag = qt_s_flag = 0;
qtv_codec_lstnum = qtv_codec_num;
qts_codec_lstnum = qts_codec_num;
qtv_chunkoff_lstnum = qtv_chunkoff_num;
qts_chunkoff_lstnum = qts_chunkoff_num;
qtv_samp_lstnum = qtv_samp_num;
qts_samp_lstnum = qts_samp_num;
qtv_s2chunk_lstnum = qtv_s2chunk_num;
qts_s2chunk_lstnum = qts_s2chunk_num;
file_len -= 8;
break;
case QT_moov:
qt_moov_flag = xaTRUE;
file_len -= 8;
break;
case QT_mdia:
case QT_minf:
case QT_stbl:
case QT_edts:
file_len -= 8;
break;
/*---------------STUFF------------------*/
case QT_mvhd:
QT_Read_MVHD(fin,&qt_mvhdr);
file_len -= len;
break;
case QT_tkhd:
QT_Read_TKHD(fin,&qt_tkhdr);
file_len -= len;
break;
case QT_elst:
QT_Read_ELST(fin,&qt_start_offset,&qt_init_duration);
file_len -= len;
break;
case QT_mdhd:
QT_Read_MDHD(fin,&qt_mdhdr);
file_len -= len;
break;
case QT_hdlr:
QT_Read_HDLR(fin,len,&qt_hdlr_hdr);
file_len -= len;
break;
/*--------------DATA CHUNKS-------------*/
case QT_mdat: /* data is included in .rsrc - assumed flatness */
fseek(fin,(len-8),1); /* skip over it for now */
qt_data_flag = xaTRUE;
break;
case QT_stsd:
qt_video_flag = 0;
if (qt_v_flag)
{
if (QT_Read_Video_STSD(anim_hdr,qt,fin) == xaFALSE) return(xaFALSE);
}
else if (qt_s_flag) QT_Read_Audio_STSD(fin);
else fseek(fin,(len-8),1);
file_len -= len;
break;
case QT_stts:
if (qt_v_flag)
QT_Read_STTS(fin,(len-8),&qtv_t2samp_num,&qtv_t2samps);
/*POD NOTE: AUDIO don't need? probably, just haven't been bit by it yet.
else if (qt_s_flag)
QT_Read_STTS(fin,(len-8),&qts_t2samp_num,&qts_t2samps);
*/
else fseek(fin,(len-8),1);
file_len -= len;
break;
case QT_stss:
QT_Read_STSS(fin);
file_len -= len;
break;
case QT_stco:
if (qt_v_flag) QT_Read_STCO(fin,&qtv_chunkoff_num,&qtv_chunkoffs);
else if (qt_s_flag) QT_Read_STCO(fin,&qts_chunkoff_num,&qts_chunkoffs);
else fseek(fin,(len-8),1);
file_len -= len;
break;
case QT_stsz:
if (qt_v_flag) QT_Read_STSZ(fin,len,&qtv_samp_num,&qtv_samp_sizes);
else if (qt_s_flag)
QT_Read_STSZ(fin,len,&qts_samp_num,&qts_samp_sizes);
else fseek(fin,(len-8),1);
file_len -= len;
break;
case QT_stsc:
if (qt_v_flag) QT_Read_STSC(fin,len,&qtv_s2chunk_num,&qtv_s2chunks,
qtv_chunkoff_lstnum,qtv_codec_num,qtv_codec_lstnum);
else if (qt_s_flag) QT_Read_STSC(fin,len,&qts_s2chunk_num,&qts_s2chunks,
qts_chunkoff_lstnum,qts_codec_num,qts_codec_lstnum);
else fseek(fin,(len-8),1);
file_len -= len;
break;
case QT_stgs:
QT_Read_STGS(fin,len);
file_len -= len;
break;
/*-----------Sound Codec Headers--------------*/
case QT_raw00:
/*-----------Video/Sound Codec Headers--------------*/
case QT_raw:
/*-----------Video Codec Headers--------------*/
case QT_smc:
case QT_rpza:
case QT_rle:
case QT_cvid:
fprintf(stdout,"QT: Warning %08x\n",id);
fseek(fin,(len-8),1); /* skip over */
file_len -= len;
break;
/*-----------TYPE OF TRAK---------------*/
case QT_vmhd:
fseek(fin,(len-8),1);
file_len -= len; qt_v_flag = 1;
qt_vid_timescale = qt_md_timescale;
qtv_tk_timescale = qt_tk_timescale;
qtv_init_duration = qt_init_duration; qt_init_duration = 0;
qtv_start_offset = qt_start_offset; qt_start_offset = 0;
break;
case QT_smhd:
fseek(fin,(len-8),1);
file_len -= len; qt_s_flag = 1;
qt_aud_timescale = qt_md_timescale;
qts_tk_timescale = qt_tk_timescale;
qts_init_duration = qt_init_duration; qt_init_duration = 0;
qts_start_offset = qt_start_offset; qt_start_offset = 0;
break;
/************ CTAB ******************
* Color Table to be used for display 16/24 bit animations on
* 8 Bit displays.
*************************************/
case QT_ctab:
{ xaULONG i,tmp,start,end;
if (x11_display_type != XA_PSEUDOCOLOR)
{
while(len > 0) {fgetc(fin); len--; }
break;
}
if (xa_verbose) fprintf(stdout,"QT: has ctab\n");
tmp = UTIL_Get_MSB_Long(fin); /* ?? */
start = UTIL_Get_MSB_UShort(fin); /* start */
end = UTIL_Get_MSB_UShort(fin); /* end */
len -= 8;
for(i=start; i <= end; i++)
{ xaULONG idx,r,g,b;
idx = UTIL_Get_MSB_UShort(fin);
r = UTIL_Get_MSB_UShort(fin);
g = UTIL_Get_MSB_UShort(fin);
b = UTIL_Get_MSB_UShort(fin); len -= 8;
/* if (cflag & 0x8000) idx = i; */
if (idx < qt->imagec)
{
qt->cmap[idx].red = r;
qt->cmap[idx].green = g;
qt->cmap[idx].blue = b;
}
if (len <= 0) break;
} /* end of for i */
while(len > 0) {fgetc(fin); len--; }
qt->imagec = 256;
qt->chdr = ACT_Get_CMAP(qt->cmap,qt->imagec,0,qt->imagec,0,8,8,8);
qt_has_ctab = xaTRUE;
}
break;
/*--------------IGNORED FOR NOW---------*/
case QT_gmhd:
case QT_text:
case QT_clip:
case QT_skip:
case QT_udta:
case QT_dinf:
fseek(fin,(len-8),1); /* skip over */
file_len -= len;
break;
/*--------------UNKNOWN-----------------*/
default:
if ( !feof(fin) && (len <= file_len) )
{
xaLONG i;
QT_Print_ID(stdout,id,1);
fprintf(stdout," len = %x\n",len);
i = (xaLONG)(len) - 8;
while(i > 0) { i--; getc(fin); if (feof(fin)) i = 0; }
}
file_len -= len;
break;
} /* end of switch */
if ( feof(fin) )
{
file_len = 0;
if ((qt_moov_flag == xaFALSE) && (qt_data_flag == xaTRUE))
{ fprintf(stdout,"QT: file possibly truncated or missing .rsrc info.\n");
return(xaFALSE);
}
}
} /* end of while */
return(xaTRUE);
}
void QT_Print_ID(fout,id,flag)
FILE *fout;
xaLONG id,flag;
{ fprintf(fout,"%c", (char)((id >> 24) & 0xff));
fprintf(fout,"%c", (char)((id >> 16) & 0xff));
fprintf(fout,"%c", (char)((id >> 8) & 0xff));
fprintf(fout,"%c", (char) (id & 0xff));
if (flag) fprintf(fout,"(%x)",id);
}
void QT_Read_MVHD(fin,qt_mvhdr)
FILE *fin;
QT_MVHDR *qt_mvhdr;
{
xaULONG i,j;
qt_mvhdr->version = UTIL_Get_MSB_Long(fin);
qt_mvhdr->creation = UTIL_Get_MSB_Long(fin);
qt_mvhdr->modtime = UTIL_Get_MSB_Long(fin);
qt_mvhdr->timescale = UTIL_Get_MSB_Long(fin);
qt_mvhdr->duration = UTIL_Get_MSB_Long(fin);
qt_mvhdr->rate = UTIL_Get_MSB_Long(fin);
qt_mvhdr->volume = UTIL_Get_MSB_UShort(fin);
qt_mvhdr->r1 = UTIL_Get_MSB_Long(fin);
qt_mvhdr->r2 = UTIL_Get_MSB_Long(fin);
for(i=0;i<3;i++) for(j=0;j<3;j++)
qt_mvhdr->matrix[i][j]=UTIL_Get_MSB_Long(fin);
qt_mvhdr->r3 = UTIL_Get_MSB_UShort(fin);
qt_mvhdr->r4 = UTIL_Get_MSB_Long(fin);
qt_mvhdr->pv_time = UTIL_Get_MSB_Long(fin);
qt_mvhdr->post_time = UTIL_Get_MSB_Long(fin);
qt_mvhdr->sel_time = UTIL_Get_MSB_Long(fin);
qt_mvhdr->sel_durat = UTIL_Get_MSB_Long(fin);
qt_mvhdr->cur_time = UTIL_Get_MSB_Long(fin);
qt_mvhdr->nxt_tk_id = UTIL_Get_MSB_Long(fin);
if (qt_mvhdr->timescale) qt_mv_timescale = qt_mvhdr->timescale;
else qt_mv_timescale = 1000;
qt_vid_timescale = qt_mv_timescale;
DEBUG_LEVEL2
{ fprintf(stdout,"mv ver = %x timescale = %x duration = %x\n",
qt_mvhdr->version,qt_mvhdr->timescale, qt_mvhdr->duration);
fprintf(stdout," rate = %x volume = %x nxt_tk = %x\n",
qt_mvhdr->rate,qt_mvhdr->volume,qt_mvhdr->nxt_tk_id);
}
}
void QT_Read_TKHD(fin,qt_tkhdr)
FILE *fin;
QT_TKHDR *qt_tkhdr;
{ xaULONG i,j;
qt_tkhdr->version = UTIL_Get_MSB_Long(fin);
qt_tkhdr->creation = UTIL_Get_MSB_Long(fin);
qt_tkhdr->modtime = UTIL_Get_MSB_Long(fin);
qt_tkhdr->trackid = UTIL_Get_MSB_Long(fin);
qt_tkhdr->timescale = UTIL_Get_MSB_Long(fin);
qt_tkhdr->duration = UTIL_Get_MSB_Long(fin);
qt_tkhdr->time_off = UTIL_Get_MSB_Long(fin);
qt_tkhdr->priority = UTIL_Get_MSB_Long(fin);
qt_tkhdr->layer = UTIL_Get_MSB_UShort(fin);
qt_tkhdr->alt_group = UTIL_Get_MSB_UShort(fin);
qt_tkhdr->volume = UTIL_Get_MSB_UShort(fin);
for(i=0;i<3;i++) for(j=0;j<3;j++)
qt_tkhdr->matrix[i][j]=UTIL_Get_MSB_Long(fin);
qt_tkhdr->tk_width = UTIL_Get_MSB_Long(fin);
qt_tkhdr->tk_height = UTIL_Get_MSB_Long(fin);
qt_tkhdr->pad = UTIL_Get_MSB_UShort(fin);
if (qt_tkhdr->timescale) qt_tk_timescale = qt_tkhdr->timescale;
else qt_tk_timescale = qt_mv_timescale;
DEBUG_LEVEL2
{ fprintf(stdout,"tk ver = %x tk_id = %x timescale = %x\n",
qt_tkhdr->version,qt_tkhdr->trackid,qt_tkhdr->timescale);
fprintf(stdout," dur= %x timoff= %x tk_width= %x tk_height= %x\n",
qt_tkhdr->duration,qt_tkhdr->time_off,qt_tkhdr->tk_width,qt_tkhdr->tk_height);
}
}
/* PODPOD */
/* implement different between start_offset and init_duration */
void QT_Read_ELST(fin,qt_start_offset,qt_init_duration)
FILE *fin;
xaULONG *qt_start_offset;
xaULONG *qt_init_duration;
{ xaULONG i,num,version;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2 fprintf(stdout," ELST ver %x num %x\n",version,num);
for(i=0; i < num; i++)
{ xaULONG duration,time,rate,pad;
duration = UTIL_Get_MSB_Long(fin);
time = UTIL_Get_MSB_Long(fin);
rate = UTIL_Get_MSB_UShort(fin);
pad = UTIL_Get_MSB_UShort(fin);
/* This is currently a kludge with limited support */
if (i==0)
{ if (time == 0xffffffff) *qt_init_duration += duration;
else if (time != 0x0) *qt_start_offset += time;
}
DEBUG_LEVEL2 fprintf(stdout," -) dur %x tim %x rate %x\n",
duration,time,rate);
}
}
void QT_Read_MDHD(fin,qt_mdhdr)
FILE *fin;
QT_MDHDR *qt_mdhdr;
{ qt_mdhdr->version = UTIL_Get_MSB_Long(fin);
qt_mdhdr->creation = UTIL_Get_MSB_Long(fin);
qt_mdhdr->modtime = UTIL_Get_MSB_Long(fin);
qt_mdhdr->timescale = UTIL_Get_MSB_Long(fin);
qt_mdhdr->duration = UTIL_Get_MSB_Long(fin);
qt_mdhdr->language = UTIL_Get_MSB_UShort(fin);
qt_mdhdr->quality = UTIL_Get_MSB_UShort(fin);
if (qt_mdhdr->timescale) qt_md_timescale = qt_mdhdr->timescale;
else qt_md_timescale = qt_tk_timescale;
DEBUG_LEVEL2
{ fprintf(stdout,"md ver = %x timescale = %x duration = %x\n",
qt_mdhdr->version,qt_mdhdr->timescale,qt_mdhdr->duration);
fprintf(stdout," lang= %x quality= %x\n",
qt_mdhdr->language,qt_mdhdr->quality);
}
}
void QT_Read_HDLR(fin,len,qt_hdlr_hdr)
FILE *fin;
xaLONG len;
QT_HDLR_HDR *qt_hdlr_hdr;
{ qt_hdlr_hdr->version = UTIL_Get_MSB_Long(fin);
qt_hdlr_hdr->type = UTIL_Get_MSB_Long(fin);
qt_hdlr_hdr->subtype = UTIL_Get_MSB_Long(fin);
qt_hdlr_hdr->vendor = UTIL_Get_MSB_Long(fin);
qt_hdlr_hdr->flags = UTIL_Get_MSB_Long(fin);
qt_hdlr_hdr->mask = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2
{ fprintf(stdout," ver = %x ",qt_hdlr_hdr->version);
QT_Print_ID(stdout,qt_hdlr_hdr->type,1);
QT_Print_ID(stdout,qt_hdlr_hdr->subtype,1);
QT_Print_ID(stdout,qt_hdlr_hdr->vendor,0);
fprintf(stdout,"\n flags= %x mask= %x\n",
qt_hdlr_hdr->flags,qt_hdlr_hdr->mask);
}
/* Read Handler Name if Present */
if (len > 32)
{ len -= 32;
QT_Read_Name(fin,len);
}
}
/*********************************************
* Read and Parse Video Codecs
*
**********/
xaULONG QT_Read_Video_STSD(anim_hdr,qt,fin)
XA_ANIM_HDR *anim_hdr;
XA_ANIM_SETUP *qt;
FILE *fin;
{ xaULONG i,version,num,cur,sup;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2 fprintf(stdout," ver = %x num = %x\n", version,num);
if (qtv_codecs == 0)
{ qtv_codec_num = num;
qtv_codecs = (QTV_CODEC_HDR *)malloc(qtv_codec_num * sizeof(QTV_CODEC_HDR));
if (qtv_codecs==0) TheEnd1("QT STSD: malloc err");
cur = 0;
}
else
{ QTV_CODEC_HDR *tcodecs;
tcodecs = (QTV_CODEC_HDR *)malloc((qtv_codec_num+num) * sizeof(QTV_CODEC_HDR));
if (tcodecs==0) TheEnd1("QT STSD: malloc err");
for(i=0;i<qtv_codec_num;i++) tcodecs[i] = qtv_codecs[i];
cur = qtv_codec_num;
qtv_codec_num += num;
FREE(qtv_codecs,0x900d);
qtv_codecs = tcodecs;
}
sup = 0;
for(i=0; i < num; i++)
{
sup |= QT_Read_Video_Codec_HDR(anim_hdr,qt, &qtv_codecs[cur], fin );
DEBUG_LEVEL1 fprintf(stdout,"CODEC %d) sup=%d\n",i,sup);
cur++;
}
if (sup == 0) return(xaFALSE);
qt_video_flag = 1;
if ( (qt->pic==0) && (xa_buffer_flag == xaTRUE))
{
qt->pic_size = qt->max_imagex * qt->max_imagey;
if ( (cmap_true_map_flag == xaTRUE) && (qt->depth > 8) )
qt->pic = (xaUBYTE *) malloc(3 * qt->pic_size);
else qt->pic = (xaUBYTE *) malloc( XA_PIC_SIZE(qt->pic_size) );
if (qt->pic == 0) TheEnd1("QT_Buffer_Action: malloc failed");
}
return(xaTRUE);
}
xaULONG QT_Read_Video_Codec_HDR(anim_hdr,qt,c_hdr,fin)
XA_ANIM_HDR *anim_hdr;
XA_ANIM_SETUP *qt;
QTV_CODEC_HDR *c_hdr;
FILE *fin;
{
xaULONG id;
xaLONG len,i,codec_ret;
xaULONG unk_0,unk_1,unk_2,unk_3,unk_4,unk_5,unk_6,unk_7,flag;
xaULONG vendor,temp_qual,spat_qual,h_res,v_res;
len = UTIL_Get_MSB_Long(fin);
id = UTIL_Get_MSB_Long(fin);
unk_0 = UTIL_Get_MSB_Long(fin);
unk_1 = UTIL_Get_MSB_Long(fin);
unk_2 = UTIL_Get_MSB_UShort(fin);
unk_3 = UTIL_Get_MSB_UShort(fin);
vendor = UTIL_Get_MSB_Long(fin);
temp_qual = UTIL_Get_MSB_Long(fin);
spat_qual = UTIL_Get_MSB_Long(fin);
qt->imagex = UTIL_Get_MSB_UShort(fin);
qt->imagey = UTIL_Get_MSB_UShort(fin);
h_res = UTIL_Get_MSB_UShort(fin);
unk_4 = UTIL_Get_MSB_UShort(fin);
v_res = UTIL_Get_MSB_UShort(fin);
unk_5 = UTIL_Get_MSB_UShort(fin);
unk_6 = UTIL_Get_MSB_Long(fin);
unk_7 = UTIL_Get_MSB_UShort(fin);
QT_Read_Name(fin,32);
qt->depth = UTIL_Get_MSB_UShort(fin);
flag = UTIL_Get_MSB_UShort(fin);
len -= 0x56;
/* init now in case of early out */
c_hdr->width = qt->imagex;
c_hdr->height = qt->imagey;
c_hdr->depth = qt->depth;
c_hdr->compression = id;
c_hdr->chdr = 0;
if ( (qt->depth == 8) || (qt->depth == 40)
|| (qt->depth == 4) || (qt->depth == 36) ) /* generate colormap */
{
if (qt->depth & 0x04) qt->imagec = 16;
else qt->imagec = 256;
if (qt->depth < 32) QT_Create_Default_Cmap(qt->cmap,qt->imagec);
else /* grayscale */
{
if ((id == QT_jpeg) || (id == QT_cvid))
QT_Create_Gray_Cmap(qt->cmap,1,qt->imagec);
else QT_Create_Gray_Cmap(qt->cmap,0,qt->imagec);
}
if ( !(flag & 0x08) && (len) ) /* colormap isn't default */
{
xaULONG start,end,p,r,g,b,cflag;
DEBUG_LEVEL1 fprintf(stdout,"reading colormap. flag %x\n",flag);
start = UTIL_Get_MSB_Long(fin); /* is this start or something else? */
cflag = UTIL_Get_MSB_UShort(fin); /* is this end or total number? */
end = UTIL_Get_MSB_UShort(fin); /* is this end or total number? */
len -= 8;
DEBUG_LEVEL1 fprintf(stdout," start %x end %x cflag %x\n",start,end,cflag);
for(i = start; i <= end; i++)
{
p = UTIL_Get_MSB_UShort(fin);
r = UTIL_Get_MSB_UShort(fin);
g = UTIL_Get_MSB_UShort(fin);
b = UTIL_Get_MSB_UShort(fin); len -= 8;
if (cflag & 0x8000) p = i;
if (p<qt->imagec)
{
qt->cmap[p].red = r;
qt->cmap[p].green = g;
qt->cmap[p].blue = b;
}
if (len <= 0) break;
}
}
}
while(len > 0) {fgetc(fin); len--; }
qt->compression = qt_codec_hdr.compression = id;
qt_codec_hdr.x = qt->imagex;
qt_codec_hdr.y = qt->imagey;
qt_codec_hdr.depth = qt->depth;
qt_codec_hdr.anim_hdr = (void *)anim_hdr;
qt_codec_hdr.avi_ctab_flag = xaFALSE;
/* Query to see if Video Compression is supported or not */
{ xaULONG q = 0;
while(q < (QT_QUERY_CNT) )
{
codec_ret = qt_query_func[q](&qt_codec_hdr);
if (codec_ret == CODEC_SUPPORTED)
{
qt->imagex = qt_codec_hdr.x;
qt->imagey = qt_codec_hdr.y;
qt->depth = qt_codec_hdr.depth;
qt->compression = qt_codec_hdr.compression;
c_hdr->xapi_rev = qt_codec_hdr.xapi_rev;
c_hdr->decoder = qt_codec_hdr.decoder;
c_hdr->depth = qt_codec_hdr.depth; /* depth */
c_hdr->dlta_extra = qt_codec_hdr.extra;
break;
}
else if (codec_ret == CODEC_UNSUPPORTED) break;
q++;
}
}
/*** Return False if Codec is Unknown or Not Supported */
if (codec_ret != CODEC_SUPPORTED)
{ char tmpbuf[256];
if (codec_ret == CODEC_UNKNOWN)
{ xaULONG ii,a[4],dd = qt->compression;
for(ii=0; ii<4; ii++)
{ a[ii] = dd & 0xff; dd >>= 8;
if ((a[ii] < ' ') || (a[ii] > 'z')) a[ii] = '.';
}
sprintf(tmpbuf,"Unknown %c%c%c%c(%08x)",
(char)a[3],(char)a[2],(char)a[1],(char)a[0],qt->compression);
qt_codec_hdr.description = tmpbuf;
}
if (xa_verbose)
fprintf(stdout," Video Codec: %s",qt_codec_hdr.description);
else fprintf(stdout,"QT Video Codec: %s",qt_codec_hdr.description);
fprintf(stdout," is unsupported by this executable.(E%x)\n",qt->depth);
/* point 'em to the readme's */
switch(qt->compression)
{
case QT_iv31:
case QT_IV31:
case QT_iv32:
case QT_IV32:
case QT_YVU9:
case QT_YUV9:
fprintf(stdout," Please see the file \"indeo.readme\".\n");
break;
case QT_cvid:
case QT_CVID:
fprintf(stdout," Please see the file \"cinepak.readme\".\n");
break;
}
return(0);
}
if (qt->depth == 40) qt->depth = 8;
/* Print out Video Codec info */
if (xa_verbose) fprintf(stdout," Video Codec: %s depth=%d\n",
qt_codec_hdr.description,qt->depth);
if (qt->depth == 1)
{
qt->imagec = 2;
qt->cmap[0].red = qt->cmap[0].green = qt->cmap[0].blue = 0;
qt->cmap[1].red = qt->cmap[1].green = qt->cmap[1].blue = 0xff;
qt->chdr = ACT_Get_CMAP(qt->cmap,qt->imagec,0,qt->imagec,0,8,8,8);
}
else if ((qt->depth == 8) || (qt->depth == 4))
{
qt->chdr = ACT_Get_CMAP(qt->cmap,qt->imagec,0,qt->imagec,0,16,16,16);
}
else if ( (qt->depth >= 16) && (qt->depth <= 32) )
{
if ( (cmap_true_map_flag == xaFALSE) /* depth 16 and not true_map */
|| (xa_buffer_flag == xaFALSE) )
{
if (cmap_true_to_332 == xaTRUE)
qt->chdr = CMAP_Create_332(qt->cmap,&qt->imagec);
else qt->chdr = CMAP_Create_Gray(qt->cmap,&qt->imagec);
}
else { qt->imagec = 0; qt->chdr = 0; }
}
c_hdr->width = qt->imagex;
c_hdr->height = qt->imagey;
c_hdr->depth = qt->depth;
c_hdr->compression = qt->compression;
c_hdr->chdr = qt->chdr;
if (qt->imagex > qt->max_imagex) qt->max_imagex = qt->imagex;
if (qt->imagey > qt->max_imagey) qt->max_imagey = qt->imagey;
return(1);
}
void QT_Read_Name(fin,r_len)
FILE *fin;
xaLONG r_len;
{
xaULONG len,d,i;
len = fgetc(fin); r_len--;
if (r_len == 0) r_len = len;
if (len > r_len) fprintf(stdout,"QT_Name: len(%d) > r_len(%d)\n",len,r_len);
DEBUG_LEVEL2 fprintf(stdout," (%d/%d) ",len,r_len);
for(i=0;i<r_len;i++)
{
d = fgetc(fin) & 0x7f;
if (i < len) DEBUG_LEVEL2 fputc(d,stdout);
}
DEBUG_LEVEL2 fputc('\n',stdout);
}
/* Time To Sample */
void QT_Read_STTS(fin,len,qt_t2samp_num,qt_t2samps)
FILE *fin;
xaLONG len;
xaULONG *qt_t2samp_num;
QT_T2SAMP_HDR **qt_t2samps;
{
xaULONG version,num,i,samp_cnt,duration,cur;
xaULONG t2samp_num = *qt_t2samp_num;
QT_T2SAMP_HDR *t2samps = *qt_t2samps;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin); len -= 8;
DEBUG_LEVEL2 fprintf(stdout," ver=%x num of entries = %x\n",version,num);
/* POD TEST chunk len/num mismatch - deal with it - ignore given num??*/
num = len >> 3;
if (t2samps==0)
{
t2samp_num = num;
t2samps = (QT_T2SAMP_HDR *)malloc(num * sizeof(QT_T2SAMP_HDR));
if (t2samps==0) TheEnd1("QT_Read_STTS: malloc err");
cur = 0;
}
else
{ QT_T2SAMP_HDR *t_t2samp;
t_t2samp = (QT_T2SAMP_HDR *)
malloc((t2samp_num + num) * sizeof(QT_T2SAMP_HDR));
if (t_t2samp==0) TheEnd1("QT_Read_STTS: malloc err");
for(i=0;i<t2samp_num;i++) t_t2samp[i] = t2samps[i];
cur = t2samp_num;
t2samp_num += num;
FREE(t2samps,0x900e);
t2samps = t_t2samp;
}
for(i=0;i<num;i++)
{ double ftime;
samp_cnt = UTIL_Get_MSB_Long(fin);
duration = UTIL_Get_MSB_Long(fin); len -= 8;
if (duration == 0) duration = 1;
/* NOTE: convert to 1000ms per second */
t2samps[cur].cnt = samp_cnt;
ftime = (1000.0 * (double)(duration)) / (double)(qt_vid_timescale);
t2samps[cur].time = (xaULONG)(ftime);
ftime -= (double)(t2samps[cur].time);
t2samps[cur].timelo = (xaULONG)(ftime * (double)(1<<24));
DEBUG_LEVEL2 fprintf(stdout," %d) samp_cnt=%x duration = %x time %d timelo %d ftime %f\n",
i,samp_cnt,duration,t2samps[cur].time,t2samps[cur].timelo,ftime);
cur++;
}
*qt_t2samp_num = t2samp_num;
*qt_t2samps = t2samps;
while(len > 0) {len--; getc(fin); }
}
/* Sync Sample */
void QT_Read_STSS(fin)
FILE *fin;
{
xaULONG version,num,i,j;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2
{
fprintf(stdout," ver=%x num of entries = %x\n",version,num);
j = 0;
fprintf(stdout," ");
}
for(i=0;i<num;i++)
{
xaULONG samp_num;
samp_num = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2
{
fprintf(stdout,"%x ",samp_num); j++;
if (j >= 8) {fprintf(stdout,"\n "); j=0; }
}
}
DEBUG_LEVEL2 fprintf(stdout,"\n");
}
/* Sample to Chunk */
void QT_Read_STSC(fin,len,qt_s2chunk_num,qt_s2chunks,
chunkoff_lstnum,codec_num,codec_lstnum)
FILE *fin;
xaLONG len;
xaULONG *qt_s2chunk_num;
QT_S2CHUNK_HDR **qt_s2chunks;
xaULONG chunkoff_lstnum,codec_num,codec_lstnum;
{
xaULONG version,num,i,cur,stsc_type,last;
xaULONG s2chunk_num = *qt_s2chunk_num;
QT_S2CHUNK_HDR *s2chunks = *qt_s2chunks;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin); len -= 16;
i = (num)?(len/num):(0);
if (i == 16)
{
DEBUG_LEVEL2 fprintf(stdout,"STSC: OLD STYLE\n");
len -= num * 16; stsc_type = 0;
}
else
{
DEBUG_LEVEL2 fprintf(stdout,"STSC: NEW STYLE\n");
len -= num * 12; stsc_type = 1;
}
DEBUG_LEVEL2 fprintf(stdout," ver=%x num of entries = %x\n",version,num);
if (s2chunks == 0)
{
s2chunk_num = num;
s2chunks = (QT_S2CHUNK_HDR *)malloc((num+1) * sizeof(QT_S2CHUNK_HDR));
cur = 0;
}
else
{ QT_S2CHUNK_HDR *ts2c;
ts2c = (QT_S2CHUNK_HDR *)
malloc( (s2chunk_num + num + 1) * sizeof(QT_S2CHUNK_HDR));
for(i=0;i<s2chunk_num;i++) ts2c[i] = s2chunks[i];
cur = s2chunk_num;
s2chunk_num += num;
FREE(s2chunks,0x900f);
s2chunks = ts2c;
}
last = 0;
for(i=0;i<num;i++)
{
xaULONG first_chk,samp_per,chunk_tag;
if (stsc_type == 0) /* 4 entries */
{ xaULONG tmp;
first_chk = UTIL_Get_MSB_Long(fin);
tmp = UTIL_Get_MSB_Long(fin);
samp_per = UTIL_Get_MSB_Long(fin);
chunk_tag = UTIL_Get_MSB_Long(fin);
if (i > 0) s2chunks[cur-1].num = first_chk - last;
last = first_chk;
if (i==(num-1))
{
if (qt_stgs_num)
{
s2chunks[cur].num = (qt_stgs_num - first_chk) + 1;
qt_stgs_num = 0;
}
else
{
fprintf(stdout,"STSC: old style but not stgs chunk warning\n");
s2chunks[cur].num = 100000;
}
}
}
else /* 3 entries */
{
first_chk = UTIL_Get_MSB_Long(fin);
samp_per = UTIL_Get_MSB_Long(fin);
chunk_tag = UTIL_Get_MSB_Long(fin);
s2chunks[cur].num = samp_per;
}
DEBUG_LEVEL2
fprintf(stdout," %d-%d) first_chunk=%x samp_per_chk=%x chk_tag=%x\n",
i,cur,first_chk,samp_per,chunk_tag);
/* start at 0 not 1 and account for previous chunks */
s2chunks[cur].first = first_chk - 1 + chunkoff_lstnum;
if (chunk_tag > (codec_num - codec_lstnum))
{ samp_per = chunk_tag = 1; }
s2chunks[cur].tag = chunk_tag - 1 + codec_lstnum;
cur++;
}
s2chunks[cur].first = 0;
s2chunks[cur].num = 0;
s2chunks[cur].tag = 0;
DEBUG_LEVEL2 fprintf(stdout," STSC left over %d\n",len);
while (len > 0) { fgetc(fin); len--; }
*qt_s2chunk_num = s2chunk_num;
*qt_s2chunks = s2chunks;
}
/* Sample Size */
void QT_Read_STSZ(fin,len,qt_samp_num,qt_samp_sizes)
FILE *fin;
xaLONG len;
xaULONG *qt_samp_num,**qt_samp_sizes;
{
xaULONG version,samp_size,num,i,cur;
xaULONG samp_num = *qt_samp_num;
xaULONG *samp_sizes = *qt_samp_sizes;
version = UTIL_Get_MSB_Long(fin);
samp_size = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin);
len = (len - 20) / 4; /* number of stored samples */
DEBUG_LEVEL2 fprintf(stdout," ver=%x samp_size=%x entries= %x stored entries=%x\n",version,samp_size,num,len);
if (samp_size == 1) num = 1; /* for AUDIO PODNOTE: rethink this */
if (samp_sizes == 0)
{
samp_num = num;
samp_sizes = (xaULONG *)malloc(num * sizeof(xaULONG));
if (samp_sizes == 0) {fprintf(stdout,"malloc err 0\n"); TheEnd();}
cur = 0;
}
else /*TRAK*/
{
xaULONG *tsamps;
tsamps = (xaULONG *)malloc((samp_num + num) * sizeof(xaULONG));
if (tsamps == 0) {fprintf(stdout,"malloc err 0\n"); TheEnd();}
for(i=0; i<samp_num; i++) tsamps[i] = samp_sizes[i];
cur = samp_num;
samp_num += num;
FREE(samp_sizes,0x9010);
samp_sizes = tsamps;
}
for(i=0;i<num;i++)
{
if (i < len) samp_sizes[cur] = UTIL_Get_MSB_Long(fin);
else if (i==0) samp_sizes[cur] = samp_size;
else samp_sizes[cur] = samp_sizes[cur-1];
cur++;
}
*qt_samp_num = samp_num;
*qt_samp_sizes = samp_sizes;
}
/* Chunk Offset */
void QT_Read_STCO(fin,qt_chunkoff_num,qt_chunkoffs)
FILE *fin;
xaULONG *qt_chunkoff_num;
xaULONG **qt_chunkoffs;
{
xaULONG version,num,i,cur;
xaULONG chunkoff_num = *qt_chunkoff_num;
xaULONG *chunkoffs = *qt_chunkoffs;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2 fprintf(stdout," ver=%x entries= %x\n",version,num);
if (chunkoffs == 0)
{
chunkoff_num = num;
chunkoffs = (xaULONG *)malloc(num * sizeof(xaULONG) );
cur = 0;
}
else
{
xaULONG *tchunks;
tchunks = (xaULONG *)malloc((chunkoff_num + num) * sizeof(xaULONG));
if (tchunks == 0) {fprintf(stdout,"malloc err 0\n"); TheEnd();}
for(i=0; i<chunkoff_num; i++) tchunks[i] = chunkoffs[i];
cur = chunkoff_num;
chunkoff_num += num;
FREE(chunkoffs,0x9011);
chunkoffs = tchunks;
}
for(i=0;i<num;i++) {chunkoffs[cur] = UTIL_Get_MSB_Long(fin); cur++; }
*qt_chunkoff_num = chunkoff_num;
*qt_chunkoffs = chunkoffs;
DEBUG_LEVEL2
{ for(i=0;i<num;i++) fprintf(stdout," STCO %d) %x\n",i,
chunkoffs[ i ]);
}
}
xaULONG QT_Read_Video_Data(qt,fin,anim_hdr)
XA_ANIM_SETUP *qt;
FILE *fin;
XA_ANIM_HDR *anim_hdr;
{
xaULONG d,ret,i;
xaULONG cur_samp,cur_s2chunk,nxt_s2chunk;
xaULONG cur_t2samp,nxt_t2samp;
xaULONG tag;
xaULONG cur_off;
xaULONG unsupported_flag = xaFALSE;
XA_ACTION *act;
qtv_init_duration += qts_start_offset;
qt->cmap_frame_num = qtv_chunkoff_num / cmap_sample_cnt;
nxt_t2samp = cur_t2samp = 0;
if (qtv_t2samps)
{
if (xa_jiffy_flag) { qt->vid_time = xa_jiffy_flag; qt->vid_timelo = 0; }
else
{
qt->vid_time = qtv_t2samps[cur_t2samp].time;
qt->vid_timelo = qtv_t2samps[cur_t2samp].timelo;
}
nxt_t2samp += qtv_t2samps[cur_t2samp].cnt;
} else { qt->vid_time = XA_GET_TIME(100); qt->vid_timelo = 0; }
cur_off=0;
cur_samp = 0;
cur_s2chunk = 0;
nxt_s2chunk = qtv_s2chunks[cur_s2chunk + 1].first;
tag = qtv_s2chunks[cur_s2chunk].tag;
qt->imagex = qtv_codecs[tag].width;
qt->imagey = qtv_codecs[tag].height;
qt->depth = qtv_codecs[tag].depth;
qt->compression = qtv_codecs[tag].compression;
qt->chdr = qtv_codecs[tag].chdr;
/* Loop through chunk offsets */
for(i=0; i < qtv_chunkoff_num; i++)
{
xaULONG size,chunk_off,num_samps;
ACT_DLTA_HDR *dlta_hdr;
chunk_off = qtv_chunkoffs[i];
/* survive RPZA despite corruption(offsets commonly corrupted).*/
/* MOVE THIS INTO RPZA DECODE
check size of RPZA again size in codec.
*/
if ( (i == nxt_s2chunk) && ((cur_s2chunk+1) < qtv_s2chunk_num) )
{
cur_s2chunk++;
nxt_s2chunk = qtv_s2chunks[cur_s2chunk + 1].first;
}
num_samps = qtv_s2chunks[cur_s2chunk].num;
/* Check tags and possibly move to new codec */
if (qtv_s2chunks[cur_s2chunk].tag >= qtv_codec_num)
{
fprintf(stdout,"QT Data: Warning stsc chunk invalid %d tag %d\n",
cur_s2chunk,qtv_s2chunks[cur_s2chunk].tag);
}
else if (qtv_s2chunks[cur_s2chunk].tag != tag)
{
tag = qtv_s2chunks[cur_s2chunk].tag;
qt->imagex = qtv_codecs[tag].width;
qt->imagey = qtv_codecs[tag].height;
qt->depth = qtv_codecs[tag].depth;
qt->compression = qtv_codecs[tag].compression;
qt->chdr = qtv_codecs[tag].chdr;
}
/* Read number of samples in each chunk */
cur_off = chunk_off;
while(num_samps--)
{
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);
if ( (cur_samp >= nxt_t2samp) && (cur_t2samp < qtv_t2samp_num) )
{
cur_t2samp++;
if (xa_jiffy_flag) { qt->vid_time = xa_jiffy_flag; qt->vid_timelo = 0; }
else
{ qt->vid_time = qtv_t2samps[cur_t2samp].time;
qt->vid_timelo = qtv_t2samps[cur_t2samp].timelo;
}
nxt_t2samp += qtv_t2samps[cur_t2samp].cnt;
}
size = qtv_samp_sizes[cur_samp];
act = ACT_Get_Action(anim_hdr,ACT_DELTA);
if (xa_file_flag == xaTRUE)
{
dlta_hdr = (ACT_DLTA_HDR *) malloc(sizeof(ACT_DLTA_HDR));
if (dlta_hdr == 0) TheEnd1("QT rle: malloc failed");
act->data = (xaUBYTE *)dlta_hdr;
dlta_hdr->flags = ACT_SNGL_BUF;
dlta_hdr->fsize = size;
dlta_hdr->fpos = cur_off;
if (size > qt->max_fvid_size) qt->max_fvid_size = size;
}
else
{
d = size + (sizeof(ACT_DLTA_HDR));
dlta_hdr = (ACT_DLTA_HDR *) malloc( d );
if (dlta_hdr == 0) TheEnd1("QT rle: malloc failed");
act->data = (xaUBYTE *)dlta_hdr;
dlta_hdr->flags = ACT_SNGL_BUF | DLTA_DATA;
dlta_hdr->fpos = 0; dlta_hdr->fsize = size;
fseek(fin,cur_off,0);
ret = fread( dlta_hdr->data, size, 1, fin);
if (ret != 1)
{ fprintf(stdout,"QT: video read err\n");
if (qt_frame_cnt) return(xaTRUE);
else return(xaFALSE); }
}
cur_off += size;
if (qtv_init_duration)
{ xaLONG t_time, t_timelo; double ftime;
ftime = (1000.0 * (double)(qtv_init_duration))
/ (double)(qtv_tk_timescale);
t_time = (xaULONG)(ftime);
ftime -= (double)(t_time);
t_timelo = (xaULONG)(ftime * (double)(1<<24));
t_time += qt->vid_time;
t_timelo += qt->vid_timelo;
while(t_timelo >= 1<<24) { t_timelo -= 1<<24; t_time++; }
QT_Add_Frame(t_time,t_timelo,act);
qtv_init_duration = 0;
}
else
QT_Add_Frame(qt->vid_time,qt->vid_timelo,act);
dlta_hdr->xpos = dlta_hdr->ypos = 0;
dlta_hdr->xsize = qt->imagex;
dlta_hdr->ysize = qt->imagey;
dlta_hdr->special = 0;
if (qtv_codecs[tag].decoder)
{ dlta_hdr->extra = qtv_codecs[tag].dlta_extra;
dlta_hdr->delta = qtv_codecs[tag].decoder;
dlta_hdr->xapi_rev = qtv_codecs[tag].xapi_rev;
}
else
{
if (unsupported_flag == xaFALSE) /* only output single warning */
{
fprintf(stdout,"QT: Sections of this movie use an unsupported Video Codec\n");
fprintf(stdout," and are therefore NOT viewable.\n");
unsupported_flag = xaTRUE;
}
act->type = ACT_NOP;
}
ACT_Setup_DeltaOLD(qt,act,dlta_hdr,fin);
cur_samp++;
if (cur_samp >= qtv_samp_num) break;
} /* end of sample number */
if (cur_samp >= qtv_samp_num) break;
} /* end of chunk_offset loop */
return(xaTRUE);
}
xaULONG QT_Parse_Bin(fin)
FILE *fin;
{
xaULONG pos,len,cid,total;
fseek(fin,0,2);
total = ftell(fin);
/* Read over Header */
fseek(fin,0,0);
pos = len = UTIL_Get_MSB_Long(fin);
cid = UTIL_Get_MSB_Long(fin);
if (cid == QT_mdat)
{
fseek(fin,0,0);
if (len == 0)
{
fprintf(stdout,"QT: This is only .data fork. Need .rsrc fork\n");
return(0);
}
else return(1);
}
else if (cid == QT_moov)
{ fseek(fin,0,0);
return(1);
}
if (len < 4) return(0);
DEBUG_LEVEL1 fprintf(stdout,"QT_Parse_Bin: pos %x Total %x\n",pos,total);
while( pos < total )
{ xaULONG d1,d2;
fseek(fin,pos,0);
len = UTIL_Get_MSB_Long(fin);
d1 = UTIL_Get_MSB_Long(fin);
d2 = UTIL_Get_MSB_Long(fin);
/* Search for QT_moov Chunk
*
* MacBinary Format
* len: length of BIN chunk something
* d1 : possibly QT Chunk size
* d2 : possibly QT Chunk ID
*
* Quicktime Format
* len: QT Chunk size
* d1 : QT Chunk ID
*
* NOTE: this is to catch Quicktime files missing the "mdat" atom and
* it will only work is the very next chunk is "moov".
*/
if (d1 == QT_moov) /* Quicktime Format */
{
qt_data_flag = xaTRUE; /* .data chunk is unmarked */
fseek(fin,pos,0);
return(1);
}
pos += 4; /* move past "len" */
if (d2 == QT_moov) /* MacBinary Format */
{
fseek(fin,pos,0);
return(1);
}
if (len == 0) return(0);
pos += len;
}
return(0);
}
/*********************************************
* Read and Parse Audio Codecs
*
**********/
void QT_Read_Audio_STSD(fin)
FILE *fin;
{ xaULONG i,version,num,cur,sup;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin);
DEBUG_LEVEL2 fprintf(stdout," ver = %x num = %x\n", version,num);
if (qts_codecs == 0)
{ qts_codec_num = num;
qts_codecs = (QTS_CODEC_HDR *)malloc(qts_codec_num * sizeof(QTS_CODEC_HDR));
if (qts_codecs==0) TheEnd1("QT STSD: malloc err");
cur = 0;
}
else
{ QTS_CODEC_HDR *tcodecs;
tcodecs = (QTS_CODEC_HDR *)malloc((qts_codec_num+num) * sizeof(QTS_CODEC_HDR))
;
if (tcodecs==0) TheEnd1("QT STSD: malloc err");
for(i=0;i<qts_codec_num;i++) tcodecs[i] = qts_codecs[i];
cur = qts_codec_num;
qts_codec_num += num;
FREE(qts_codecs,0x9014);
qts_codecs = tcodecs;
}
sup = 0;
for(i=0; i < num; i++)
{
sup |= QT_Read_Audio_Codec_HDR( &qts_codecs[cur], fin );
cur++;
}
if (sup == 0)
{
if (qt_audio_attempt == xaTRUE)
{
fprintf(stdout,"QT Audio Codec not supported\n");
qt_audio_attempt = xaFALSE;
}
}
}
xaULONG QT_Read_Audio_Codec_HDR(c_hdr,fin)
QTS_CODEC_HDR *c_hdr;
FILE *fin;
{ xaULONG len;
xaULONG ret = 1;
len = UTIL_Get_MSB_Long(fin);
c_hdr->compression = UTIL_Get_MSB_Long(fin);
c_hdr->dref_id = UTIL_Get_MSB_Long(fin);
c_hdr->version = UTIL_Get_MSB_Long(fin);
c_hdr->codec_rev = UTIL_Get_MSB_Long(fin);
c_hdr->vendor = UTIL_Get_MSB_Long(fin);
c_hdr->chan_num = UTIL_Get_MSB_UShort(fin);
c_hdr->bits_samp = UTIL_Get_MSB_UShort(fin);
/* Some Mac Shareware program screws up when converting AVI's to QT's */
if ( (c_hdr->bits_samp == 1)
&& ( (c_hdr->compression == QT_twos)
|| (c_hdr->compression == QT_raw)
|| (c_hdr->compression == QT_raw00)
) ) c_hdr->bits_samp = 8;
c_hdr->comp_id = UTIL_Get_MSB_UShort(fin);
c_hdr->pack_size = UTIL_Get_MSB_UShort(fin);
c_hdr->samp_rate = UTIL_Get_MSB_UShort(fin);
c_hdr->pad = UTIL_Get_MSB_UShort(fin);
if (xa_verbose)
{
fprintf(stdout," Audio Codec: "); QT_Audio_Type(c_hdr->compression);
fprintf(stdout," Rate=%d Chans=%d Bps=%d\n",
c_hdr->samp_rate,c_hdr->chan_num,c_hdr->bits_samp);
}
if (c_hdr->compression == QT_twos) c_hdr->compression =XA_AUDIO_SIGNED;
else if (c_hdr->compression == QT_raw) c_hdr->compression =XA_AUDIO_LINEAR;
else if (c_hdr->compression == QT_raw00) c_hdr->compression =XA_AUDIO_LINEAR;
else if (c_hdr->compression == QT_ima4) c_hdr->compression =XA_AUDIO_IMA4;
else ret = 0;
if (c_hdr->bits_samp==8) c_hdr->bps = 1;
else if (c_hdr->bits_samp==16) c_hdr->bps = 2;
else if (c_hdr->bits_samp==32) c_hdr->bps = 4;
else c_hdr->bps = 100 + c_hdr->bits_samp;
if (c_hdr->bps > 2) ret = 0;
if (c_hdr->chan_num > 2) ret = 0;
if ( (c_hdr->bps==2)
&& ((c_hdr->compression & XA_AUDIO_TYPE_MASK) != XA_AUDIO_IMA4) )
{
c_hdr->compression |= XA_AUDIO_BPS_2_MSK;
c_hdr->compression |= XA_AUDIO_BIGEND_MSK; /* only has meaning >= 2 bps */
}
if (c_hdr->chan_num==2)
{
c_hdr->compression |= XA_AUDIO_STEREO_MSK;
c_hdr->bps *= 2;
}
return(ret);
}
void QT_Audio_Type(type)
xaULONG type;
{ switch(type)
{ case QT_raw: fprintf(stdout,"PCM"); break;
case QT_raw00: fprintf(stdout,"PCM0"); break;
case QT_twos: fprintf(stdout,"TWOS"); break;
case QT_MAC6: fprintf(stdout,"MAC6"); break;
case QT_ima4: fprintf(stdout,"IMA4"); break;
default: fprintf(stdout,"(%c%c%c%c)(%08x)",
(char)((type>>24)&0xff), (char)((type>>16)&0xff),
(char)((type>>8)&0xff),(char)((type)&0xff),type);
break;
}
}
/**************
*
*
*******/
xaULONG QT_Read_Audio_Data(qt,fin,anim_hdr)
XA_ANIM_SETUP *qt;
FILE *fin;
XA_ANIM_HDR *anim_hdr;
{
xaULONG ret,i;
xaULONG cur_s2chunk,nxt_s2chunk;
xaULONG tag;
DEBUG_LEVEL1 fprintf(stdout,"QT_Read_Audio: attempt %x co# %d\n",
qt_audio_attempt,qts_chunkoff_num);
cur_s2chunk = 0;
nxt_s2chunk = qts_s2chunks[cur_s2chunk + 1].first;
tag = qts_s2chunks[cur_s2chunk].tag;
qt_audio_freq = qts_codecs[tag].samp_rate;
qt_audio_chans = qts_codecs[tag].chan_num;
qt_audio_bps = qts_codecs[tag].bps;
qt_audio_type = qts_codecs[tag].compression;
qt_audio_end = 1;
/* Initial Silence if any. PODNOTE: Eventually Modify for Middle silence */
qts_init_duration += qtv_start_offset;
if (qts_init_duration)
{ xaULONG snd_size;
snd_size = (qt_audio_freq * qts_init_duration) / qts_tk_timescale;
if (XA_Add_Sound(anim_hdr,0,XA_AUDIO_NOP, -1, qt_audio_freq,
snd_size, &qt->aud_time, &qt->aud_timelo, 0, 0) == xaFALSE)
return(xaFALSE);
}
/* Loop through chunk offsets */
for(i=0; i < qts_chunkoff_num; i++)
{ xaULONG size,chunk_off,num_samps,snd_size;
xaULONG blockalign, sampsblock;
if ( (i == nxt_s2chunk) && ((cur_s2chunk+1) < qts_s2chunk_num) )
{
cur_s2chunk++;
nxt_s2chunk = qts_s2chunks[cur_s2chunk+1].first;
}
num_samps = qts_s2chunks[cur_s2chunk].num; /* * sttz */
/* Check tags and possibly move to new codec */
if (qts_s2chunks[cur_s2chunk].tag >= qts_codec_num)
{
fprintf(stdout,"QT Data: Warning stsc chunk invalid %d tag %d\n",
cur_s2chunk,qts_s2chunks[cur_s2chunk].tag);
}
else if (qts_s2chunks[cur_s2chunk].tag != tag)
{
tag = qts_s2chunks[cur_s2chunk].tag;
qt_audio_freq = qts_codecs[tag].samp_rate;
qt_audio_chans = qts_codecs[tag].chan_num;
qt_audio_bps = qts_codecs[tag].bps;
qt_audio_type = qts_codecs[tag].compression;
qt_audio_end = 1;
}
/* NOTE: THE STSZ CHUNKS FOR AUDIO IS TOTALLY F****D UP AND INCONSISTENT
* ACROSS MANY ANIMATIONS. CURRENTLY JUST IGNORE THIS. */
if (i < qts_samp_num) size = qts_samp_sizes[i];
else if (qts_samp_num) size = qts_samp_sizes[qts_samp_num-1];
else size = qt_audio_bps;
if (size > qt_audio_bps)
{
fprintf(stdout,"QT UNIQE AUDIO: sz %d bps %d\n",size,qt_audio_bps);
}
chunk_off = qts_chunkoffs[i];
/*
fprintf(stdout,"SND: off %08x size %08x\n",chunk_off, size);
*/
if (qt_audio_type == XA_AUDIO_IMA4_M)
{ xaULONG numblks = num_samps / 0x40;
snd_size = numblks * 0x22;
blockalign = 0x22;
sampsblock = 0x40;
}
else if (qt_audio_type == XA_AUDIO_IMA4_S)
{ xaULONG numblks = num_samps / 0x40;
snd_size = numblks * 0x44;
blockalign = 0x44;
sampsblock = 0x40;
}
else
{ snd_size = num_samps * qt_audio_bps;
blockalign = qt_audio_bps; /* not really valid yet */
sampsblock = 0x1;
}
DEBUG_LEVEL1 fprintf(stdout,"snd_size %x numsamps %x size %x bps %d off %x\n",
snd_size,num_samps,size,qt_audio_bps,chunk_off);
if (xa_file_flag == xaTRUE)
{
if (XA_Add_Sound(anim_hdr,0,qt_audio_type, chunk_off, qt_audio_freq,
snd_size, &qt->aud_time, &qt->aud_timelo,
blockalign,sampsblock) == xaFALSE) return(xaFALSE);
if (snd_size > qt->max_faud_size) qt->max_faud_size = snd_size;
}
else
{ xaUBYTE *snd_data = (xaUBYTE *)malloc(snd_size);
if (snd_data==0) TheEnd1("QT aud_dat: malloc err");
fseek(fin,chunk_off,0); /* move to start of chunk data */
ret = fread(snd_data, snd_size, 1, fin);
if (ret != 1)
{ fprintf(stdout,"QT: snd rd err\n");
return(xaTRUE);
}
if (XA_Add_Sound(anim_hdr,snd_data,qt_audio_type, -1, qt_audio_freq,
snd_size, &qt->aud_time, &qt->aud_timelo,
blockalign,sampsblock) == xaFALSE) return(xaFALSE);
}
} /* end of chunk_offset loop */
return(xaTRUE);
}
/********
* Have No Clue
*
****/
void QT_Read_STGS(fin,len)
FILE *fin;
xaLONG len;
{
xaULONG i,version,num;
xaULONG samps,pad;
version = UTIL_Get_MSB_Long(fin);
num = UTIL_Get_MSB_Long(fin); len -= 16;
qt_stgs_num = 0;
for(i=0; i<num; i++)
{
samps = UTIL_Get_MSB_Long(fin);
pad = UTIL_Get_MSB_Long(fin); len -= 8;
qt_stgs_num += samps;
}
while(len > 0) {len--; getc(fin); }
}
/* MAX */
int qt_4map[] = {
0xff, 0xfb, 0xff,
0xef, 0xd9, 0xbb,
0xe8, 0xc9, 0xb1,
0x93, 0x65, 0x5e,
0xfc, 0xde, 0xe8,
0x9d, 0x88, 0x91,
0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
0xff, 0xff, 0xff,
0x47, 0x48, 0x37,
0x7a, 0x5e, 0x55,
0xdf, 0xd0, 0xab,
0xff, 0xfb, 0xf9,
0xe8, 0xca, 0xc5,
0x8a, 0x7c, 0x77
};
/**************************************
* QT_Create_Default_Cmap
*
* This routine recreates the Default Apple colormap.
* It is an educated quess after looking at two quicktime animations
* and may not be totally correct, but seems to work okay.
*/
void QT_Create_Default_Cmap(cmap,cnum)
ColorReg *cmap;
xaULONG cnum;
{
xaLONG r,g,b,i;
if (cnum == 16)
{
for(i=0;i<15;i++)
{ int d = i * 3;
cmap[i].red = 0x101 * qt_4map[d];
cmap[i].green = 0x101 * qt_4map[d+1];
cmap[i].blue = 0x101 * qt_4map[d+2];
}
}
else
{ static xaUBYTE pat[10] = {0xee,0xdd,0xbb,0xaa,0x88,0x77,0x55,0x44,0x22,0x11};
r = g = b = 0xff;
for(i=0;i<215;i++)
{
cmap[i].red = 0x101 * r;
cmap[i].green = 0x101 * g;
cmap[i].blue = 0x101 * b;
b -= 0x33;
if (b < 0) { b = 0xff; g -= 0x33; if (g < 0) { g = 0xff; r -= 0x33; } }
}
for(i=0;i<10;i++)
{ xaULONG d = 0x101 * pat[i];
xaULONG ip = 215 + i;
cmap[ip].red = d; cmap[ip].green = cmap[ip].blue = 0; ip += 10;
cmap[ip].green = d; cmap[ip].red = cmap[ip].blue = 0; ip += 10;
cmap[ip].blue = d; cmap[ip].red = cmap[ip].green = 0; ip += 10;
cmap[ip].red = cmap[ip].green = cmap[ip].blue = d;
}
cmap[255].red = cmap[255].green = cmap[255].blue = 0x00;
}
}
/**************************************
* QT_Create_Gray_Cmap
*
* This routine recreates the Default Gray Apple colormap.
*/
void QT_Create_Gray_Cmap(cmap,flag,num)
ColorReg *cmap;
xaULONG flag; /* flag=0 0=>255; flag=1 255=>0 */
xaULONG num; /* size of color map */
{
xaLONG g,i;
if (num == 256)
{
g = (flag)?(0x00):(0xff);
for(i=0;i<256;i++)
{
cmap[i].red = 0x101 * g;
cmap[i].green = 0x101 * g;
cmap[i].blue = 0x101 * g;
cmap[i].gray = 0x101 * g;
if (flag) g++; else g--;
}
}
else if (num == 16)
{
g = 0xf;
for(i=0;i<16;i++)
{
cmap[i].red = 0x1111 * g;
cmap[i].green = 0x1111 * g;
cmap[i].blue = 0x1111 * g;
cmap[i].gray = 0x1111 * g;
g--;
}
}
}