avilib.c 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838
  1. /*
  2. * avilib.c
  3. *
  4. * Copyright (C) Thomas �streich - June 2001
  5. * multiple audio track support Copyright (C) 2002 Thomas �streich
  6. *
  7. * Original code:
  8. * Copyright (C) 1999 Rainer Johanni <Rainer@Johanni.de>
  9. *
  10. * This file is part of transcode, a linux video stream processing tool
  11. *
  12. * transcode is free software; you can redistribute it and/or modify
  13. * it under the terms of the GNU General Public License as published by
  14. * the Free Software Foundation; either version 2, or (at your option)
  15. * any later version.
  16. *
  17. * transcode is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with GNU Make; see the file COPYING. If not, write to
  24. * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  25. *
  26. */
  27. #include "avilib.h"
  28. //#include <time.h>
  29. #define INFO_LIST
  30. /* The following variable indicates the kind of error */
  31. long AVI_errno;
  32. #define MAX_INFO_STRLEN 64
  33. static char id_str[MAX_INFO_STRLEN];
  34. #define FRAME_RATE_SCALE 1000000
  35. #ifndef PACKAGE
  36. #define PACKAGE "my"
  37. #define VERSION "0.00"
  38. #endif
  39. #ifndef O_BINARY
  40. /* win32 wants a binary flag to open(); this sets it to null
  41. on platforms that don't have it. */
  42. #define O_BINARY 0
  43. #endif
  44. /*******************************************************************
  45. * *
  46. * Utilities for writing an AVI File *
  47. * *
  48. *******************************************************************/
  49. static size_t avi_read(int fd, char *buf, size_t len)
  50. {
  51. size_t n = 0;
  52. size_t r = 0;
  53. while (r < len) {
  54. n = read (fd, buf + r, len - r);
  55. if (n <= 0)
  56. return r;
  57. r += n;
  58. }
  59. return r;
  60. }
  61. static size_t avi_write (int fd, char *buf, size_t len)
  62. {
  63. size_t n = 0;
  64. size_t r = 0;
  65. while (r < len) {
  66. n = write (fd, buf + r, len - r);
  67. if (n < 0)
  68. return n;
  69. r += n;
  70. }
  71. return r;
  72. }
  73. /* HEADERBYTES: The number of bytes to reserve for the header */
  74. #define HEADERBYTES 2048
  75. /* AVI_MAX_LEN: The maximum length of an AVI file, we stay a bit below
  76. the 2GB limit (Remember: 2*10^9 is smaller than 2 GB) */
  77. #define AVI_MAX_LEN (UINT_MAX-(1<<20)*16-HEADERBYTES)
  78. #define PAD_EVEN(x) ( ((x)+1) & ~1 )
  79. /* Copy n into dst as a 4 byte, little endian number.
  80. Should also work on big endian machines */
  81. static void long2str(unsigned char *dst, int n)
  82. {
  83. dst[0] = (n )&0xff;
  84. dst[1] = (n>> 8)&0xff;
  85. dst[2] = (n>>16)&0xff;
  86. dst[3] = (n>>24)&0xff;
  87. }
  88. /* Convert a string of 4 or 2 bytes to a number,
  89. also working on big endian machines */
  90. static unsigned long str2ulong(unsigned char *str)
  91. {
  92. return ( str[0] | (str[1]<<8) | (str[2]<<16) | (str[3]<<24) );
  93. }
  94. static unsigned long str2ushort(unsigned char *str)
  95. {
  96. return ( str[0] | (str[1]<<8) );
  97. }
  98. /* Calculate audio sample size from number of bits and number of channels.
  99. This may have to be adjusted for eg. 12 bits and stereo */
  100. static int avi_sampsize(avi_t *AVI, int j)
  101. {
  102. int s;
  103. s = ((AVI->track[j].a_bits+7)/8)*AVI->track[j].a_chans;
  104. // if(s==0) s=1; /* avoid possible zero divisions */
  105. if(s<4) s=4; /* avoid possible zero divisions */
  106. return s;
  107. }
  108. /* Add a chunk (=tag and data) to the AVI file,
  109. returns -1 on write error, 0 on success */
  110. static int avi_add_chunk(avi_t *AVI, unsigned char *tag, unsigned char *data, int length)
  111. {
  112. unsigned char c[8];
  113. /* Copy tag and length int c, so that we need only 1 write system call
  114. for these two values */
  115. memcpy(c,tag,4);
  116. long2str(c+4,length);
  117. /* Output tag, length and data, restore previous position
  118. if the write fails */
  119. length = PAD_EVEN(length);
  120. if( avi_write(AVI->fdes,(char *)c,8) != 8 ||
  121. avi_write(AVI->fdes,(char *)data,length) != length )
  122. {
  123. lseek(AVI->fdes,AVI->pos,SEEK_SET);
  124. AVI_errno = AVI_ERR_WRITE;
  125. return -1;
  126. }
  127. /* Update file position */
  128. AVI->pos += 8 + length;
  129. //fprintf(stderr, "pos=%lu %s\n", AVI->pos, tag);
  130. return 0;
  131. }
  132. static int avi_add_index_entry(avi_t *AVI, unsigned char *tag, long flags, unsigned long pos, unsigned long len)
  133. {
  134. void *ptr;
  135. if(AVI->n_idx>=AVI->max_idx) {
  136. ptr = realloc((void *)AVI->idx,(AVI->max_idx+4096)*16);
  137. if(ptr == 0) {
  138. AVI_errno = AVI_ERR_NO_MEM;
  139. return -1;
  140. }
  141. AVI->max_idx += 4096;
  142. AVI->idx = (unsigned char((*)[16]) ) ptr;
  143. }
  144. /* Add index entry */
  145. // fprintf(stderr, "INDEX %s %ld %lu %lu\n", tag, flags, pos, len);
  146. memcpy(AVI->idx[AVI->n_idx],tag,4);
  147. long2str(AVI->idx[AVI->n_idx]+ 4,flags);
  148. long2str(AVI->idx[AVI->n_idx]+ 8, pos);
  149. long2str(AVI->idx[AVI->n_idx]+12, len);
  150. /* Update counter */
  151. AVI->n_idx++;
  152. if(len>AVI->max_len) AVI->max_len=len;
  153. return 0;
  154. }
  155. /*
  156. AVI_open_output_file: Open an AVI File and write a bunch
  157. of zero bytes as space for the header.
  158. returns a pointer to avi_t on success, a zero pointer on error
  159. */
  160. avi_t* AVI_open_output_file(char * filename)
  161. {
  162. avi_t *AVI;
  163. int i;
  164. int mask = 0;
  165. unsigned char AVI_header[HEADERBYTES];
  166. /* Allocate the avi_t struct and zero it */
  167. AVI = (avi_t *) malloc(sizeof(avi_t));
  168. if(AVI==0)
  169. {
  170. AVI_errno = AVI_ERR_NO_MEM;
  171. return 0;
  172. }
  173. memset((void *)AVI,0,sizeof(avi_t));
  174. /* Since Linux needs a long time when deleting big files,
  175. we do not truncate the file when we open it.
  176. Instead it is truncated when the AVI file is closed */
  177. /* mask = umask (0);
  178. umask (mask);*/
  179. AVI->fdes = open(filename, O_RDWR|O_CREAT|O_BINARY, 0644 &~ mask);
  180. if (AVI->fdes < 0)
  181. {
  182. AVI_errno = AVI_ERR_OPEN;
  183. free(AVI);
  184. return 0;
  185. }
  186. /* Write out HEADERBYTES bytes, the header will go here
  187. when we are finished with writing */
  188. for (i=0;i<HEADERBYTES;i++) AVI_header[i] = 0;
  189. i = avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES);
  190. if (i != HEADERBYTES)
  191. {
  192. close(AVI->fdes);
  193. AVI_errno = AVI_ERR_WRITE;
  194. free(AVI);
  195. return 0;
  196. }
  197. AVI->pos = HEADERBYTES;
  198. AVI->mode = AVI_MODE_WRITE; /* open for writing */
  199. //init
  200. AVI->anum = 0;
  201. AVI->aptr = 0;
  202. return AVI;
  203. }
  204. void AVI_set_video(avi_t *AVI, int width, int height, double fps, char *compressor)
  205. {
  206. /* may only be called if file is open for writing */
  207. if(AVI->mode==AVI_MODE_READ) return;
  208. AVI->width = width;
  209. AVI->height = height;
  210. AVI->fps = fps;
  211. if(strncmp(compressor, "RGB", 3)==0) {
  212. memset(AVI->compressor, 0, 4);
  213. } else {
  214. memcpy(AVI->compressor,compressor,4);
  215. }
  216. AVI->compressor[4] = 0;
  217. avi_update_header(AVI);
  218. }
  219. void AVI_set_audio(avi_t *AVI, int channels, long rate, int bits, int format, long mp3rate)
  220. {
  221. /* may only be called if file is open for writing */
  222. if(AVI->mode==AVI_MODE_READ) return;
  223. //inc audio tracks
  224. AVI->aptr=AVI->anum;
  225. ++AVI->anum;
  226. if(AVI->anum > AVI_MAX_TRACKS) {
  227. fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS);
  228. exit(1);
  229. }
  230. AVI->track[AVI->aptr].a_chans = channels;
  231. AVI->track[AVI->aptr].a_rate = rate;
  232. AVI->track[AVI->aptr].a_bits = bits;
  233. AVI->track[AVI->aptr].a_fmt = format;
  234. AVI->track[AVI->aptr].mp3rate = mp3rate;
  235. avi_update_header(AVI);
  236. }
  237. #define OUT4CC(s) \
  238. if(nhb<=HEADERBYTES-4) memcpy(AVI_header+nhb,s,4); nhb += 4
  239. #define OUTLONG(n) \
  240. if(nhb<=HEADERBYTES-4) long2str(AVI_header+nhb,n); nhb += 4
  241. #define OUTSHRT(n) \
  242. if(nhb<=HEADERBYTES-2) { \
  243. AVI_header[nhb ] = (n )&0xff; \
  244. AVI_header[nhb+1] = (n>>8)&0xff; \
  245. } \
  246. nhb += 2
  247. //ThOe write preliminary AVI file header: 0 frames, max vid/aud size
  248. int avi_update_header(avi_t *AVI)
  249. {
  250. int njunk, sampsize, hasIndex, ms_per_frame, frate, flag;
  251. int movi_len, hdrl_start, strl_start, j;
  252. unsigned char AVI_header[HEADERBYTES];
  253. long nhb;
  254. //assume max size
  255. movi_len = AVI_MAX_LEN - HEADERBYTES + 4;
  256. //assume index will be written
  257. hasIndex=1;
  258. if(AVI->fps < 0.001) {
  259. frate=0;
  260. ms_per_frame=0;
  261. } else {
  262. frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5);
  263. ms_per_frame=(int) (1000000/AVI->fps + 0.5);
  264. }
  265. /* Prepare the file header */
  266. nhb = 0;
  267. /* The RIFF header */
  268. OUT4CC ("RIFF");
  269. OUTLONG(movi_len); // assume max size
  270. OUT4CC ("AVI ");
  271. /* Start the header list */
  272. OUT4CC ("LIST");
  273. OUTLONG(0); /* Length of list in bytes, don't know yet */
  274. hdrl_start = nhb; /* Store start position */
  275. OUT4CC ("hdrl");
  276. /* The main AVI header */
  277. /* The Flags in AVI File header */
  278. #define AVIF_HASINDEX 0x00000010 /* Index at end of file */
  279. #define AVIF_MUSTUSEINDEX 0x00000020
  280. #define AVIF_ISINTERLEAVED 0x00000100
  281. #define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */
  282. #define AVIF_WASCAPTUREFILE 0x00010000
  283. #define AVIF_COPYRIGHTED 0x00020000
  284. OUT4CC ("avih");
  285. OUTLONG(56); /* # of bytes to follow */
  286. OUTLONG(ms_per_frame); /* Microseconds per frame */
  287. //ThOe ->0
  288. // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */
  289. OUTLONG(0);
  290. OUTLONG(0); /* PaddingGranularity (whatever that might be) */
  291. /* Other sources call it 'reserved' */
  292. flag = AVIF_ISINTERLEAVED;
  293. if(hasIndex) flag |= AVIF_HASINDEX;
  294. if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX;
  295. OUTLONG(flag); /* Flags */
  296. OUTLONG(0); // no frames yet
  297. OUTLONG(0); /* InitialFrames */
  298. OUTLONG(AVI->anum+1);
  299. OUTLONG(0); /* SuggestedBufferSize */
  300. OUTLONG(AVI->width); /* Width */
  301. OUTLONG(AVI->height); /* Height */
  302. /* MS calls the following 'reserved': */
  303. OUTLONG(0); /* TimeScale: Unit used to measure time */
  304. OUTLONG(0); /* DataRate: Data rate of playback */
  305. OUTLONG(0); /* StartTime: Starting time of AVI data */
  306. OUTLONG(0); /* DataLength: Size of AVI data chunk */
  307. /* Start the video stream list ---------------------------------- */
  308. OUT4CC ("LIST");
  309. OUTLONG(0); /* Length of list in bytes, don't know yet */
  310. strl_start = nhb; /* Store start position */
  311. OUT4CC ("strl");
  312. /* The video stream header */
  313. OUT4CC ("strh");
  314. OUTLONG(56); /* # of bytes to follow */
  315. OUT4CC ("vids"); /* Type */
  316. OUT4CC (AVI->compressor); /* Handler */
  317. OUTLONG(0); /* Flags */
  318. OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */
  319. OUTLONG(0); /* InitialFrames */
  320. OUTLONG(FRAME_RATE_SCALE); /* Scale */
  321. OUTLONG(frate); /* Rate: Rate/Scale == samples/second */
  322. OUTLONG(0); /* Start */
  323. OUTLONG(0); // no frames yet
  324. OUTLONG(0); /* SuggestedBufferSize */
  325. OUTLONG(-1); /* Quality */
  326. OUTLONG(0); /* SampleSize */
  327. OUTLONG(0); /* Frame */
  328. OUTLONG(0); /* Frame */
  329. // OUTLONG(0); /* Frame */
  330. //OUTLONG(0); /* Frame */
  331. /* The video stream format */
  332. OUT4CC ("strf");
  333. OUTLONG(40); /* # of bytes to follow */
  334. OUTLONG(40); /* Size */
  335. OUTLONG(AVI->width); /* Width */
  336. OUTLONG(AVI->height); /* Height */
  337. OUTSHRT(1); OUTSHRT(24); /* Planes, Count */
  338. OUT4CC (AVI->compressor); /* Compression */
  339. // ThOe (*3)
  340. OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */
  341. OUTLONG(0); /* XPelsPerMeter */
  342. OUTLONG(0); /* YPelsPerMeter */
  343. OUTLONG(0); /* ClrUsed: Number of colors used */
  344. OUTLONG(0); /* ClrImportant: Number of colors important */
  345. /* Finish stream list, i.e. put number of bytes in the list to proper pos */
  346. long2str(AVI_header+strl_start-4,nhb-strl_start);
  347. /* Start the audio stream list ---------------------------------- */
  348. for(j=0; j<AVI->anum; ++j) {
  349. sampsize = avi_sampsize(AVI, j);
  350. OUT4CC ("LIST");
  351. OUTLONG(0); /* Length of list in bytes, don't know yet */
  352. strl_start = nhb; /* Store start position */
  353. OUT4CC ("strl");
  354. /* The audio stream header */
  355. OUT4CC ("strh");
  356. OUTLONG(56); /* # of bytes to follow */
  357. OUT4CC ("auds");
  358. // -----------
  359. // ThOe
  360. OUTLONG(0); /* Format (Optionally) */
  361. // -----------
  362. OUTLONG(0); /* Flags */
  363. OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */
  364. OUTLONG(0); /* InitialFrames */
  365. // ThOe /4
  366. OUTLONG(sampsize/4); /* Scale */
  367. OUTLONG(1000*AVI->track[j].mp3rate/8);
  368. OUTLONG(0); /* Start */
  369. OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */
  370. OUTLONG(0); /* SuggestedBufferSize */
  371. OUTLONG(-1); /* Quality */
  372. // ThOe /4
  373. OUTLONG(sampsize/4); /* SampleSize */
  374. OUTLONG(0); /* Frame */
  375. OUTLONG(0); /* Frame */
  376. // OUTLONG(0); /* Frame */
  377. //OUTLONG(0); /* Frame */
  378. /* The audio stream format */
  379. OUT4CC ("strf");
  380. OUTLONG(16); /* # of bytes to follow */
  381. OUTSHRT(AVI->track[j].a_fmt); /* Format */
  382. OUTSHRT(AVI->track[j].a_chans); /* Number of channels */
  383. OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */
  384. // ThOe
  385. OUTLONG(1000*AVI->track[j].mp3rate/8);
  386. //ThOe (/4)
  387. OUTSHRT(sampsize/4); /* BlockAlign */
  388. OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */
  389. /* Finish stream list, i.e. put number of bytes in the list to proper pos */
  390. long2str(AVI_header+strl_start-4,nhb-strl_start);
  391. }
  392. /* Finish header list */
  393. long2str(AVI_header+hdrl_start-4,nhb-hdrl_start);
  394. /* Calculate the needed amount of junk bytes, output junk */
  395. njunk = HEADERBYTES - nhb - 8 - 12;
  396. /* Safety first: if njunk <= 0, somebody has played with
  397. HEADERBYTES without knowing what (s)he did.
  398. This is a fatal error */
  399. if(njunk<=0)
  400. {
  401. fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n");
  402. exit(1);
  403. }
  404. OUT4CC ("JUNK");
  405. OUTLONG(njunk);
  406. memset(AVI_header+nhb,0,njunk);
  407. //11/14/01 added id string
  408. if(njunk > strlen(id_str)+8) {
  409. sprintf(id_str, "%s-%s", PACKAGE, VERSION);
  410. memcpy(AVI_header+nhb, id_str, strlen(id_str));
  411. }
  412. nhb += njunk;
  413. /* Start the movi list */
  414. OUT4CC ("LIST");
  415. OUTLONG(movi_len); /* Length of list in bytes */
  416. OUT4CC ("movi");
  417. /* Output the header, truncate the file to the number of bytes
  418. actually written, report an error if someting goes wrong */
  419. if ( lseek(AVI->fdes,0,SEEK_SET)<0 ||
  420. avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES ||
  421. lseek(AVI->fdes,AVI->pos,SEEK_SET)<0)
  422. {
  423. AVI_errno = AVI_ERR_CLOSE;
  424. return -1;
  425. }
  426. return 0;
  427. }
  428. /*
  429. Write the header of an AVI file and close it.
  430. returns 0 on success, -1 on write error.
  431. */
  432. static int avi_close_output_file(avi_t *AVI)
  433. {
  434. int ret, njunk, sampsize, hasIndex, ms_per_frame, frate, idxerror, flag;
  435. unsigned long movi_len;
  436. int hdrl_start, strl_start, j;
  437. unsigned char AVI_header[HEADERBYTES];
  438. long nhb;
  439. #ifdef INFO_LIST
  440. long info_len;
  441. // time_t calptr;
  442. #endif
  443. /* Calculate length of movi list */
  444. movi_len = AVI->pos - HEADERBYTES + 4;
  445. /* Try to ouput the index entries. This may fail e.g. if no space
  446. is left on device. We will report this as an error, but we still
  447. try to write the header correctly (so that the file still may be
  448. readable in the most cases */
  449. idxerror = 0;
  450. // fprintf(stderr, "pos=%lu, index_len=%ld \n", AVI->pos, AVI->n_idx*16);
  451. ret = avi_add_chunk(AVI, (unsigned char *)"idx1", (void*)AVI->idx, AVI->n_idx*16);
  452. hasIndex = (ret==0);
  453. //fprintf(stderr, "pos=%lu, index_len=%d\n", AVI->pos, hasIndex);
  454. if(ret) {
  455. idxerror = 1;
  456. AVI_errno = AVI_ERR_WRITE_INDEX;
  457. }
  458. /* Calculate Microseconds per frame */
  459. if(AVI->fps < 0.001) {
  460. frate=0;
  461. ms_per_frame=0;
  462. } else {
  463. frate = (int) (FRAME_RATE_SCALE*AVI->fps + 0.5);
  464. ms_per_frame=(int) (1000000/AVI->fps + 0.5);
  465. }
  466. /* Prepare the file header */
  467. nhb = 0;
  468. /* The RIFF header */
  469. OUT4CC ("RIFF");
  470. OUTLONG(AVI->pos - 8); /* # of bytes to follow */
  471. OUT4CC ("AVI ");
  472. /* Start the header list */
  473. OUT4CC ("LIST");
  474. OUTLONG(0); /* Length of list in bytes, don't know yet */
  475. hdrl_start = nhb; /* Store start position */
  476. OUT4CC ("hdrl");
  477. /* The main AVI header */
  478. /* The Flags in AVI File header */
  479. #define AVIF_HASINDEX 0x00000010 /* Index at end of file */
  480. #define AVIF_MUSTUSEINDEX 0x00000020
  481. #define AVIF_ISINTERLEAVED 0x00000100
  482. #define AVIF_TRUSTCKTYPE 0x00000800 /* Use CKType to find key frames */
  483. #define AVIF_WASCAPTUREFILE 0x00010000
  484. #define AVIF_COPYRIGHTED 0x00020000
  485. OUT4CC ("avih");
  486. OUTLONG(56); /* # of bytes to follow */
  487. OUTLONG(ms_per_frame); /* Microseconds per frame */
  488. //ThOe ->0
  489. // OUTLONG(10000000); /* MaxBytesPerSec, I hope this will never be used */
  490. OUTLONG(0);
  491. OUTLONG(0); /* PaddingGranularity (whatever that might be) */
  492. /* Other sources call it 'reserved' */
  493. flag = AVIF_ISINTERLEAVED;
  494. if(hasIndex) flag |= AVIF_HASINDEX;
  495. if(hasIndex && AVI->must_use_index) flag |= AVIF_MUSTUSEINDEX;
  496. OUTLONG(flag); /* Flags */
  497. OUTLONG(AVI->video_frames); /* TotalFrames */
  498. OUTLONG(0); /* InitialFrames */
  499. OUTLONG(AVI->anum+1);
  500. // if (AVI->track[0].audio_bytes)
  501. // { OUTLONG(2); } /* Streams */
  502. // else
  503. // { OUTLONG(1); } /* Streams */
  504. OUTLONG(0); /* SuggestedBufferSize */
  505. OUTLONG(AVI->width); /* Width */
  506. OUTLONG(AVI->height); /* Height */
  507. /* MS calls the following 'reserved': */
  508. OUTLONG(0); /* TimeScale: Unit used to measure time */
  509. OUTLONG(0); /* DataRate: Data rate of playback */
  510. OUTLONG(0); /* StartTime: Starting time of AVI data */
  511. OUTLONG(0); /* DataLength: Size of AVI data chunk */
  512. /* Start the video stream list ---------------------------------- */
  513. OUT4CC ("LIST");
  514. OUTLONG(0); /* Length of list in bytes, don't know yet */
  515. strl_start = nhb; /* Store start position */
  516. OUT4CC ("strl");
  517. /* The video stream header */
  518. OUT4CC ("strh");
  519. OUTLONG(56); /* # of bytes to follow */
  520. OUT4CC ("vids"); /* Type */
  521. OUT4CC (AVI->compressor); /* Handler */
  522. OUTLONG(0); /* Flags */
  523. OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */
  524. OUTLONG(0); /* InitialFrames */
  525. OUTLONG(FRAME_RATE_SCALE); /* Scale */
  526. OUTLONG(frate); /* Rate: Rate/Scale == samples/second */
  527. OUTLONG(0); /* Start */
  528. OUTLONG(AVI->video_frames); /* Length */
  529. OUTLONG(0); /* SuggestedBufferSize */
  530. OUTLONG(-1); /* Quality */
  531. OUTLONG(0); /* SampleSize */
  532. OUTLONG(0); /* Frame */
  533. OUTLONG(0); /* Frame */
  534. // OUTLONG(0); /* Frame */
  535. //OUTLONG(0); /* Frame */
  536. /* The video stream format */
  537. OUT4CC ("strf");
  538. OUTLONG(40); /* # of bytes to follow */
  539. OUTLONG(40); /* Size */
  540. OUTLONG(AVI->width); /* Width */
  541. OUTLONG(AVI->height); /* Height */
  542. OUTSHRT(1); OUTSHRT(24); /* Planes, Count */
  543. OUT4CC (AVI->compressor); /* Compression */
  544. // ThOe (*3)
  545. OUTLONG(AVI->width*AVI->height*3); /* SizeImage (in bytes?) */
  546. OUTLONG(0); /* XPelsPerMeter */
  547. OUTLONG(0); /* YPelsPerMeter */
  548. OUTLONG(0); /* ClrUsed: Number of colors used */
  549. OUTLONG(0); /* ClrImportant: Number of colors important */
  550. /* Finish stream list, i.e. put number of bytes in the list to proper pos */
  551. long2str(AVI_header+strl_start-4,nhb-strl_start);
  552. /* Start the audio stream list ---------------------------------- */
  553. for(j=0; j<AVI->anum; ++j) {
  554. //if (AVI->track[j].a_chans && AVI->track[j].audio_bytes)
  555. {
  556. sampsize = avi_sampsize(AVI, j);
  557. OUT4CC ("LIST");
  558. OUTLONG(0); /* Length of list in bytes, don't know yet */
  559. strl_start = nhb; /* Store start position */
  560. OUT4CC ("strl");
  561. /* The audio stream header */
  562. OUT4CC ("strh");
  563. OUTLONG(56); /* # of bytes to follow */
  564. OUT4CC ("auds");
  565. // -----------
  566. // ThOe
  567. OUTLONG(0); /* Format (Optionally) */
  568. // -----------
  569. OUTLONG(0); /* Flags */
  570. OUTLONG(0); /* Reserved, MS says: wPriority, wLanguage */
  571. OUTLONG(0); /* InitialFrames */
  572. // ThOe /4
  573. OUTLONG(sampsize/4); /* Scale */
  574. OUTLONG(1000*AVI->track[j].mp3rate/8);
  575. OUTLONG(0); /* Start */
  576. OUTLONG(4*AVI->track[j].audio_bytes/sampsize); /* Length */
  577. OUTLONG(0); /* SuggestedBufferSize */
  578. OUTLONG(-1); /* Quality */
  579. // ThOe /4
  580. OUTLONG(sampsize/4); /* SampleSize */
  581. OUTLONG(0); /* Frame */
  582. OUTLONG(0); /* Frame */
  583. // OUTLONG(0); /* Frame */
  584. //OUTLONG(0); /* Frame */
  585. /* The audio stream format */
  586. OUT4CC ("strf");
  587. OUTLONG(16); /* # of bytes to follow */
  588. OUTSHRT(AVI->track[j].a_fmt); /* Format */
  589. OUTSHRT(AVI->track[j].a_chans); /* Number of channels */
  590. OUTLONG(AVI->track[j].a_rate); /* SamplesPerSec */
  591. // ThOe
  592. OUTLONG(1000*AVI->track[j].mp3rate/8);
  593. //ThOe (/4)
  594. OUTSHRT(sampsize/4); /* BlockAlign */
  595. OUTSHRT(AVI->track[j].a_bits); /* BitsPerSample */
  596. /* Finish stream list, i.e. put number of bytes in the list to proper pos */
  597. }
  598. long2str(AVI_header+strl_start-4,nhb-strl_start);
  599. }
  600. /* Finish header list */
  601. long2str(AVI_header+hdrl_start-4,nhb-hdrl_start);
  602. // add INFO list --- (0.6.0pre4)
  603. #ifdef INFO_LIST
  604. OUT4CC ("LIST");
  605. //FIXME
  606. info_len = MAX_INFO_STRLEN + 12;
  607. OUTLONG(info_len);
  608. OUT4CC ("INFO");
  609. // OUT4CC ("INAM");
  610. // OUTLONG(MAX_INFO_STRLEN);
  611. // sprintf(id_str, "\t");
  612. // memset(AVI_header+nhb, 0, MAX_INFO_STRLEN);
  613. // memcpy(AVI_header+nhb, id_str, strlen(id_str));
  614. // nhb += MAX_INFO_STRLEN;
  615. OUT4CC ("ISFT");
  616. OUTLONG(MAX_INFO_STRLEN);
  617. sprintf(id_str, "%s-%s", PACKAGE, VERSION);
  618. memset(AVI_header+nhb, 0, MAX_INFO_STRLEN);
  619. memcpy(AVI_header+nhb, id_str, strlen(id_str));
  620. nhb += MAX_INFO_STRLEN;
  621. // OUT4CC ("ICMT");
  622. // OUTLONG(MAX_INFO_STRLEN);
  623. // calptr=time(NULL);
  624. // sprintf(id_str, "\t%s %s", ctime(&calptr), "");
  625. // memset(AVI_header+nhb, 0, MAX_INFO_STRLEN);
  626. // memcpy(AVI_header+nhb, id_str, 25);
  627. // nhb += MAX_INFO_STRLEN;
  628. #endif
  629. // ----------------------------
  630. /* Calculate the needed amount of junk bytes, output junk */
  631. njunk = HEADERBYTES - nhb - 8 - 12;
  632. /* Safety first: if njunk <= 0, somebody has played with
  633. HEADERBYTES without knowing what (s)he did.
  634. This is a fatal error */
  635. if(njunk<=0)
  636. {
  637. fprintf(stderr,"AVI_close_output_file: # of header bytes too small\n");
  638. exit(1);
  639. }
  640. OUT4CC ("JUNK");
  641. OUTLONG(njunk);
  642. memset(AVI_header+nhb,0,njunk);
  643. nhb += njunk;
  644. /* Start the movi list */
  645. OUT4CC ("LIST");
  646. OUTLONG(movi_len); /* Length of list in bytes */
  647. OUT4CC ("movi");
  648. /* Output the header, truncate the file to the number of bytes
  649. actually written, report an error if someting goes wrong */
  650. if ( lseek(AVI->fdes,0,SEEK_SET)<0 ||
  651. avi_write(AVI->fdes,(char *)AVI_header,HEADERBYTES)!=HEADERBYTES
  652. //|| ftruncate(AVI->fdes,AVI->pos)<0
  653. )
  654. {
  655. AVI_errno = AVI_ERR_CLOSE;
  656. return -1;
  657. }
  658. if(idxerror) return -1;
  659. return 0;
  660. }
  661. /*
  662. AVI_write_data:
  663. Add video or audio data to the file;
  664. Return values:
  665. 0 No error;
  666. -1 Error, AVI_errno is set appropriatly;
  667. */
  668. static int avi_write_data(avi_t *AVI, char *data, unsigned long length, int audio, int keyframe)
  669. {
  670. int n;
  671. unsigned char astr[5];
  672. /* Check for maximum file length */
  673. if ( (AVI->pos + 8 + length + 8 + (AVI->n_idx+1)*16) > AVI_MAX_LEN ) {
  674. AVI_errno = AVI_ERR_SIZELIM;
  675. return -1;
  676. }
  677. /* Add index entry */
  678. //set tag for current audio track
  679. sprintf((char *)astr, "0%1dwb", AVI->aptr+1);
  680. if(audio)
  681. n = avi_add_index_entry(AVI,astr,0x00,AVI->pos,length);
  682. else
  683. n = avi_add_index_entry(AVI,(unsigned char *) "00db",((keyframe)?0x10:0x0),AVI->pos,length);
  684. if(n) return -1;
  685. /* Output tag and data */
  686. if(audio)
  687. n = avi_add_chunk(AVI,(unsigned char *) astr, (unsigned char *)data,length);
  688. else
  689. n = avi_add_chunk(AVI,(unsigned char *)"00db",(unsigned char *)data,length);
  690. if (n) return -1;
  691. return 0;
  692. }
  693. int AVI_write_frame(avi_t *AVI, char *data, long bytes, int keyframe)
  694. {
  695. unsigned long pos;
  696. if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  697. pos = AVI->pos;
  698. if(avi_write_data(AVI,data,bytes,0,keyframe)) return -1;
  699. AVI->last_pos = pos;
  700. AVI->last_len = bytes;
  701. AVI->video_frames++;
  702. return 0;
  703. }
  704. int AVI_dup_frame(avi_t *AVI)
  705. {
  706. if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  707. if(AVI->last_pos==0) return 0; /* No previous real frame */
  708. if(avi_add_index_entry(AVI,(unsigned char *)"00db",0x10,AVI->last_pos,AVI->last_len)) return -1;
  709. AVI->video_frames++;
  710. AVI->must_use_index = 1;
  711. return 0;
  712. }
  713. int AVI_write_audio(avi_t *AVI, char *data, long bytes)
  714. {
  715. if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  716. if( avi_write_data(AVI,data,bytes,1,0) ) return -1;
  717. AVI->track[AVI->aptr].audio_bytes += bytes;
  718. return 0;
  719. }
  720. int AVI_append_audio(avi_t *AVI, char *data, long bytes)
  721. {
  722. long i, length, pos;
  723. unsigned char c[4];
  724. if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  725. // update last index entry:
  726. --AVI->n_idx;
  727. length = str2ulong(AVI->idx[AVI->n_idx]+12);
  728. pos = str2ulong(AVI->idx[AVI->n_idx]+8);
  729. //update;
  730. long2str(AVI->idx[AVI->n_idx]+12,length+bytes);
  731. ++AVI->n_idx;
  732. AVI->track[AVI->aptr].audio_bytes += bytes;
  733. //update chunk header
  734. lseek(AVI->fdes, pos+4, SEEK_SET);
  735. long2str(c, length+bytes);
  736. avi_write(AVI->fdes,(char *) c, 4);
  737. lseek(AVI->fdes, pos+8+length, SEEK_SET);
  738. i=PAD_EVEN(length + bytes);
  739. bytes = i - length;
  740. avi_write(AVI->fdes, data, bytes);
  741. AVI->pos = pos + 8 + i;
  742. return 0;
  743. }
  744. long AVI_bytes_remain(avi_t *AVI)
  745. {
  746. if(AVI->mode==AVI_MODE_READ) return 0;
  747. return ( AVI_MAX_LEN - (AVI->pos + 8 + 16*AVI->n_idx));
  748. }
  749. long AVI_bytes_written(avi_t *AVI)
  750. {
  751. if(AVI->mode==AVI_MODE_READ) return 0;
  752. return (AVI->pos + 8 + 16*AVI->n_idx);
  753. }
  754. int AVI_set_audio_track(avi_t *AVI, int track)
  755. {
  756. if(track < 0 || track + 1 > AVI->anum) return(-1);
  757. //this info is not written to file anyway
  758. AVI->aptr=track;
  759. return 0;
  760. }
  761. int AVI_get_audio_track(avi_t *AVI)
  762. {
  763. return(AVI->aptr);
  764. }
  765. /*******************************************************************
  766. * *
  767. * Utilities for reading video and audio from an AVI File *
  768. * *
  769. *******************************************************************/
  770. int AVI_close(avi_t *AVI)
  771. {
  772. int ret;
  773. /* If the file was open for writing, the header and index still have
  774. to be written */
  775. if(AVI->mode == AVI_MODE_WRITE)
  776. ret = avi_close_output_file(AVI);
  777. else
  778. ret = 0;
  779. /* Even if there happened an error, we first clean up */
  780. close(AVI->fdes);
  781. if(AVI->idx) free(AVI->idx);
  782. if(AVI->video_index) free(AVI->video_index);
  783. //FIXME
  784. //if(AVI->audio_index) free(AVI->audio_index);
  785. free(AVI);
  786. return ret;
  787. }
  788. #define ERR_EXIT(x) \
  789. { \
  790. AVI_close(AVI); \
  791. AVI_errno = x; \
  792. return 0; \
  793. }
  794. avi_t *AVI_open_input_file(char *filename, int getIndex)
  795. {
  796. avi_t *AVI=NULL;
  797. /* Create avi_t structure */
  798. AVI = (avi_t *) malloc(sizeof(avi_t));
  799. if(AVI==NULL)
  800. {
  801. AVI_errno = AVI_ERR_NO_MEM;
  802. return 0;
  803. }
  804. memset((void *)AVI,0,sizeof(avi_t));
  805. AVI->mode = AVI_MODE_READ; /* open for reading */
  806. /* Open the file */
  807. AVI->fdes = open(filename,O_RDONLY|O_BINARY);
  808. if(AVI->fdes < 0)
  809. {
  810. AVI_errno = AVI_ERR_OPEN;
  811. free(AVI);
  812. return 0;
  813. }
  814. avi_parse_input_file(AVI, getIndex);
  815. AVI->aptr=0; //reset
  816. return AVI;
  817. }
  818. avi_t *AVI_open_fd(int fd, int getIndex)
  819. {
  820. avi_t *AVI=NULL;
  821. /* Create avi_t structure */
  822. AVI = (avi_t *) malloc(sizeof(avi_t));
  823. if(AVI==NULL)
  824. {
  825. AVI_errno = AVI_ERR_NO_MEM;
  826. return 0;
  827. }
  828. memset((void *)AVI,0,sizeof(avi_t));
  829. AVI->mode = AVI_MODE_READ; /* open for reading */
  830. // file alread open
  831. AVI->fdes = fd;
  832. avi_parse_input_file(AVI, getIndex);
  833. AVI->aptr=0; //reset
  834. return AVI;
  835. }
  836. int avi_parse_input_file(avi_t *AVI, int getIndex)
  837. {
  838. long i, n, rate, scale, idx_type;
  839. unsigned char *hdrl_data;
  840. long header_offset=0, hdrl_len=0;
  841. long nvi, nai[AVI_MAX_TRACKS], ioff;
  842. long tot[AVI_MAX_TRACKS];
  843. int j;
  844. int lasttag = 0;
  845. int vids_strh_seen = 0;
  846. int vids_strf_seen = 0;
  847. int auds_strh_seen = 0;
  848. // int auds_strf_seen = 0;
  849. int num_stream = 0;
  850. char data[256];
  851. /* Read first 12 bytes and check that this is an AVI file */
  852. if( avi_read(AVI->fdes,data,12) != 12 ) ERR_EXIT(AVI_ERR_READ)
  853. if( strncasecmp(data ,"RIFF",4) !=0 ||
  854. strncasecmp(data+8,"AVI ",4) !=0 ) ERR_EXIT(AVI_ERR_NO_AVI)
  855. /* Go through the AVI file and extract the header list,
  856. the start position of the 'movi' list and an optionally
  857. present idx1 tag */
  858. hdrl_data = 0;
  859. while(1)
  860. {
  861. if( avi_read(AVI->fdes,data,8) != 8 ) break; /* We assume it's EOF */
  862. n = str2ulong((unsigned char *) data+4);
  863. n = PAD_EVEN(n);
  864. if(strncasecmp(data,"LIST",4) == 0)
  865. {
  866. if( avi_read(AVI->fdes,data,4) != 4 ) ERR_EXIT(AVI_ERR_READ)
  867. n -= 4;
  868. if(strncasecmp(data,"hdrl",4) == 0)
  869. {
  870. hdrl_len = n;
  871. hdrl_data = (unsigned char *) malloc(n);
  872. if(hdrl_data==0) ERR_EXIT(AVI_ERR_NO_MEM);
  873. // offset of header
  874. header_offset = lseek(AVI->fdes,0,SEEK_CUR);
  875. if( avi_read(AVI->fdes,(char *)hdrl_data,n) != n ) ERR_EXIT(AVI_ERR_READ)
  876. }
  877. else if(strncasecmp(data,"movi",4) == 0)
  878. {
  879. AVI->movi_start = lseek(AVI->fdes,0,SEEK_CUR);
  880. lseek(AVI->fdes,n,SEEK_CUR);
  881. }
  882. else
  883. lseek(AVI->fdes,n,SEEK_CUR);
  884. }
  885. else if(strncasecmp(data,"idx1",4) == 0)
  886. {
  887. /* n must be a multiple of 16, but the reading does not
  888. break if this is not the case */
  889. AVI->n_idx = AVI->max_idx = n/16;
  890. AVI->idx = (unsigned char((*)[16]) ) malloc(n);
  891. if(AVI->idx==0) ERR_EXIT(AVI_ERR_NO_MEM)
  892. if(avi_read(AVI->fdes, (char *) AVI->idx, n) != n ) ERR_EXIT(AVI_ERR_READ)
  893. }
  894. else
  895. lseek(AVI->fdes,n,SEEK_CUR);
  896. }
  897. if(!hdrl_data ) ERR_EXIT(AVI_ERR_NO_HDRL)
  898. if(!AVI->movi_start) ERR_EXIT(AVI_ERR_NO_MOVI)
  899. /* Interpret the header list */
  900. for(i=0;i<hdrl_len;)
  901. {
  902. /* List tags are completly ignored */
  903. if(strncasecmp((char *) hdrl_data+i, "LIST",4)==0) { i+= 12; continue; }
  904. n = str2ulong(hdrl_data+i+4);
  905. n = PAD_EVEN(n);
  906. /* Interpret the tag and its args */
  907. if(strncasecmp((char *)hdrl_data+i,"strh",4)==0)
  908. {
  909. i += 8;
  910. if(strncasecmp((char *)hdrl_data+i,"vids",4) == 0 && !vids_strh_seen)
  911. {
  912. memcpy(AVI->compressor,hdrl_data+i+4,4);
  913. AVI->compressor[4] = 0;
  914. // ThOe
  915. AVI->v_codech_off = header_offset + i+4;
  916. scale = str2ulong((unsigned char *)hdrl_data+i+20);
  917. rate = str2ulong(hdrl_data+i+24);
  918. if(scale!=0) AVI->fps = (double)rate/(double)scale;
  919. AVI->video_frames = str2ulong(hdrl_data+i+32);
  920. AVI->video_strn = num_stream;
  921. AVI->max_len = 0;
  922. vids_strh_seen = 1;
  923. lasttag = 1; /* vids */
  924. }
  925. else if (strncasecmp ((char *) hdrl_data+i,"auds",4) ==0 && ! auds_strh_seen)
  926. {
  927. //inc audio tracks
  928. AVI->aptr=AVI->anum;
  929. ++AVI->anum;
  930. if(AVI->anum > AVI_MAX_TRACKS) {
  931. fprintf(stderr, "error - only %d audio tracks supported\n", AVI_MAX_TRACKS);
  932. return(-1);
  933. }
  934. AVI->track[AVI->aptr].audio_bytes = str2ulong(hdrl_data+i+32)*avi_sampsize(AVI, 0);
  935. AVI->track[AVI->aptr].audio_strn = num_stream;
  936. // auds_strh_seen = 1;
  937. lasttag = 2; /* auds */
  938. // ThOe
  939. AVI->track[AVI->aptr].a_codech_off = header_offset + i;
  940. }
  941. else
  942. lasttag = 0;
  943. num_stream++;
  944. }
  945. else if(strncasecmp((char *) hdrl_data+i,"strf",4)==0)
  946. {
  947. i += 8;
  948. if(lasttag == 1)
  949. {
  950. AVI->width = str2ulong(hdrl_data+i+4);
  951. AVI->height = str2ulong(hdrl_data+i+8);
  952. vids_strf_seen = 1;
  953. //ThOe
  954. AVI->v_codecf_off = header_offset + i+16;
  955. memcpy(AVI->compressor2, hdrl_data+i+16, 4);
  956. AVI->compressor2[4] = 0;
  957. }
  958. else if(lasttag == 2)
  959. {
  960. AVI->track[AVI->aptr].a_fmt = str2ushort(hdrl_data+i );
  961. //ThOe
  962. AVI->track[AVI->aptr].a_codecf_off = header_offset + i;
  963. AVI->track[AVI->aptr].a_chans = str2ushort(hdrl_data+i+2);
  964. AVI->track[AVI->aptr].a_rate = str2ulong (hdrl_data+i+4);
  965. //ThOe: read mp3bitrate
  966. AVI->track[AVI->aptr].mp3rate = 8*str2ulong(hdrl_data+i+8)/1000;
  967. //:ThOe
  968. AVI->track[AVI->aptr].a_bits = str2ushort(hdrl_data+i+14);
  969. // auds_strf_seen = 1;
  970. }
  971. lasttag = 0;
  972. }
  973. else
  974. {
  975. i += 8;
  976. lasttag = 0;
  977. }
  978. i += n;
  979. }
  980. free(hdrl_data);
  981. if(!vids_strh_seen || !vids_strf_seen) ERR_EXIT(AVI_ERR_NO_VIDS)
  982. AVI->video_tag[0] = AVI->video_strn/10 + '0';
  983. AVI->video_tag[1] = AVI->video_strn%10 + '0';
  984. AVI->video_tag[2] = 'd';
  985. AVI->video_tag[3] = 'b';
  986. /* Audio tag is set to "99wb" if no audio present */
  987. if(!AVI->track[0].a_chans) AVI->track[0].audio_strn = 99;
  988. for(j=0; j<AVI->anum; ++j) {
  989. AVI->track[j].audio_tag[0] = (j+1)/10 + '0';
  990. AVI->track[j].audio_tag[1] = (j+1)%10 + '0';
  991. AVI->track[j].audio_tag[2] = 'w';
  992. AVI->track[j].audio_tag[3] = 'b';
  993. }
  994. lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
  995. /* get index if wanted */
  996. if(!getIndex) return(0);
  997. /* if the file has an idx1, check if this is relative
  998. to the start of the file or to the start of the movi list */
  999. idx_type = 0;
  1000. if(AVI->idx)
  1001. {
  1002. long pos, len;
  1003. /* Search the first videoframe in the idx1 and look where
  1004. it is in the file */
  1005. for(i=0;i<AVI->n_idx;i++)
  1006. if( strncasecmp((char *) AVI->idx[i],(char *) AVI->video_tag,3)==0 ) break;
  1007. if(i>=AVI->n_idx) ERR_EXIT(AVI_ERR_NO_VIDS)
  1008. pos = str2ulong(AVI->idx[i]+ 8);
  1009. len = str2ulong(AVI->idx[i]+12);
  1010. lseek(AVI->fdes,pos,SEEK_SET);
  1011. if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ)
  1012. if( strncasecmp((char *)data,(char *)AVI->idx[i],4)==0 &&
  1013. str2ulong((unsigned char *)data+4)==len )
  1014. {
  1015. idx_type = 1; /* Index from start of file */
  1016. }
  1017. else
  1018. {
  1019. lseek(AVI->fdes,pos+AVI->movi_start-4,SEEK_SET);
  1020. if(avi_read(AVI->fdes,data,8)!=8) ERR_EXIT(AVI_ERR_READ)
  1021. if( strncasecmp((char *)data,(char *)AVI->idx[i],4)==0 && str2ulong((unsigned char *)data+4)==len )
  1022. {
  1023. idx_type = 2; /* Index from start of movi list */
  1024. }
  1025. }
  1026. /* idx_type remains 0 if neither of the two tests above succeeds */
  1027. }
  1028. if(idx_type == 0)
  1029. {
  1030. /* we must search through the file to get the index */
  1031. lseek(AVI->fdes, AVI->movi_start, SEEK_SET);
  1032. AVI->n_idx = 0;
  1033. while(1)
  1034. {
  1035. if( avi_read(AVI->fdes,data,8) != 8 ) break;
  1036. n = str2ulong((unsigned char *)data+4);
  1037. /* The movi list may contain sub-lists, ignore them */
  1038. if(strncasecmp(data,"LIST",4)==0)
  1039. {
  1040. lseek(AVI->fdes,4,SEEK_CUR);
  1041. continue;
  1042. }
  1043. /* Check if we got a tag ##db, ##dc or ##wb */
  1044. if( ( (data[2]=='d' || data[2]=='D') &&
  1045. (data[3]=='b' || data[3]=='B' || data[3]=='c' || data[3]=='C') )
  1046. || ( (data[2]=='w' || data[2]=='W') &&
  1047. (data[3]=='b' || data[3]=='B') ) )
  1048. {
  1049. avi_add_index_entry(AVI,(unsigned char *) data,0,lseek(AVI->fdes,0,SEEK_CUR)-8,n);
  1050. }
  1051. lseek(AVI->fdes,PAD_EVEN(n),SEEK_CUR);
  1052. }
  1053. idx_type = 1;
  1054. }
  1055. /* Now generate the video index and audio index arrays */
  1056. nvi = 0;
  1057. for(j=0; j<AVI->anum; ++j) nai[j] = 0;
  1058. for(i=0;i<AVI->n_idx;i++) {
  1059. if(strncasecmp((char *)AVI->idx[i],(char *) AVI->video_tag,3) == 0) nvi++;
  1060. for(j=0; j<AVI->anum; ++j) if(strncasecmp((char *)AVI->idx[i], AVI->track[j].audio_tag,4) == 0) nai[j]++;
  1061. }
  1062. AVI->video_frames = nvi;
  1063. for(j=0; j<AVI->anum; ++j) AVI->track[j].audio_chunks = nai[j];
  1064. // fprintf(stderr, "chunks = %ld %d %s\n", AVI->track[0].audio_chunks, AVI->anum, AVI->track[0].audio_tag);
  1065. if(AVI->video_frames==0) ERR_EXIT(AVI_ERR_NO_VIDS);
  1066. AVI->video_index = (video_index_entry *) malloc(nvi*sizeof(video_index_entry));
  1067. if(AVI->video_index==0) ERR_EXIT(AVI_ERR_NO_MEM);
  1068. for(j=0; j<AVI->anum; ++j) {
  1069. if(AVI->track[j].audio_chunks) {
  1070. AVI->track[j].audio_index = (audio_index_entry *) malloc(nai[j]*sizeof(audio_index_entry));
  1071. if(AVI->track[j].audio_index==0) ERR_EXIT(AVI_ERR_NO_MEM);
  1072. }
  1073. }
  1074. nvi = 0;
  1075. for(j=0; j<AVI->anum; ++j) nai[j] = tot[j] = 0;
  1076. ioff = idx_type == 1 ? 8 : AVI->movi_start+4;
  1077. for(i=0;i<AVI->n_idx;i++) {
  1078. //video
  1079. if(strncasecmp((char *)AVI->idx[i],(char *)AVI->video_tag,3) == 0) {
  1080. AVI->video_index[nvi].key = str2ulong(AVI->idx[i]+ 4);
  1081. AVI->video_index[nvi].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
  1082. AVI->video_index[nvi].len = str2ulong(AVI->idx[i]+12);
  1083. nvi++;
  1084. }
  1085. //audio
  1086. for(j=0; j<AVI->anum; ++j) {
  1087. if(strncasecmp((char *)AVI->idx[i],AVI->track[j].audio_tag,4) == 0) {
  1088. AVI->track[j].audio_index[nai[j]].pos = str2ulong(AVI->idx[i]+ 8)+ioff;
  1089. AVI->track[j].audio_index[nai[j]].len = str2ulong(AVI->idx[i]+12);
  1090. AVI->track[j].audio_index[nai[j]].tot = tot[j];
  1091. tot[j] += AVI->track[j].audio_index[nai[j]].len;
  1092. nai[j]++;
  1093. }
  1094. }
  1095. }
  1096. for(j=0; j<AVI->anum; ++j) AVI->track[j].audio_bytes = tot[j];
  1097. /* Reposition the file */
  1098. lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
  1099. AVI->video_pos = 0;
  1100. return(0);
  1101. }
  1102. long AVI_video_frames(avi_t *AVI)
  1103. {
  1104. return AVI->video_frames;
  1105. }
  1106. int AVI_video_width(avi_t *AVI)
  1107. {
  1108. return AVI->width;
  1109. }
  1110. int AVI_video_height(avi_t *AVI)
  1111. {
  1112. return AVI->height;
  1113. }
  1114. double AVI_frame_rate(avi_t *AVI)
  1115. {
  1116. return AVI->fps;
  1117. }
  1118. char* AVI_video_compressor(avi_t *AVI)
  1119. {
  1120. return AVI->compressor2;
  1121. }
  1122. long AVI_max_video_chunk(avi_t *AVI)
  1123. {
  1124. return AVI->max_len;
  1125. }
  1126. int AVI_audio_tracks(avi_t *AVI)
  1127. {
  1128. return(AVI->anum);
  1129. }
  1130. int AVI_audio_channels(avi_t *AVI)
  1131. {
  1132. return AVI->track[AVI->aptr].a_chans;
  1133. }
  1134. long AVI_audio_mp3rate(avi_t *AVI)
  1135. {
  1136. return AVI->track[AVI->aptr].mp3rate;
  1137. }
  1138. int AVI_audio_bits(avi_t *AVI)
  1139. {
  1140. return AVI->track[AVI->aptr].a_bits;
  1141. }
  1142. int AVI_audio_format(avi_t *AVI)
  1143. {
  1144. return AVI->track[AVI->aptr].a_fmt;
  1145. }
  1146. long AVI_audio_rate(avi_t *AVI)
  1147. {
  1148. return AVI->track[AVI->aptr].a_rate;
  1149. }
  1150. long AVI_audio_bytes(avi_t *AVI)
  1151. {
  1152. return AVI->track[AVI->aptr].audio_bytes;
  1153. }
  1154. long AVI_audio_chunks(avi_t *AVI)
  1155. {
  1156. return AVI->track[AVI->aptr].audio_chunks;
  1157. }
  1158. long AVI_audio_codech_offset(avi_t *AVI)
  1159. {
  1160. return AVI->track[AVI->aptr].a_codech_off;
  1161. }
  1162. long AVI_audio_codecf_offset(avi_t *AVI)
  1163. {
  1164. return AVI->track[AVI->aptr].a_codecf_off;
  1165. }
  1166. long AVI_video_codech_offset(avi_t *AVI)
  1167. {
  1168. return AVI->v_codech_off;
  1169. }
  1170. long AVI_video_codecf_offset(avi_t *AVI)
  1171. {
  1172. return AVI->v_codecf_off;
  1173. }
  1174. long AVI_frame_size(avi_t *AVI, long frame)
  1175. {
  1176. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1177. if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1178. if(frame < 0 || frame >= AVI->video_frames) return 0;
  1179. return(AVI->video_index[frame].len);
  1180. }
  1181. long AVI_audio_size(avi_t *AVI, long frame)
  1182. {
  1183. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1184. if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1185. if(frame < 0 || frame >= AVI->track[AVI->aptr].audio_chunks) return 0;
  1186. return(AVI->track[AVI->aptr].audio_index[frame].len);
  1187. }
  1188. long AVI_get_video_position(avi_t *AVI, long frame)
  1189. {
  1190. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1191. if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1192. if(frame < 0 || frame >= AVI->video_frames) return 0;
  1193. return(AVI->video_index[frame].pos);
  1194. }
  1195. int AVI_seek_start(avi_t *AVI)
  1196. {
  1197. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1198. lseek(AVI->fdes,AVI->movi_start,SEEK_SET);
  1199. AVI->video_pos = 0;
  1200. return 0;
  1201. }
  1202. int AVI_set_video_position(avi_t *AVI, long frame)
  1203. {
  1204. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1205. if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1206. if (frame < 0 ) frame = 0;
  1207. AVI->video_pos = frame;
  1208. return 0;
  1209. }
  1210. int AVI_set_audio_bitrate(avi_t *AVI, long bitrate)
  1211. {
  1212. if(AVI->mode==AVI_MODE_READ) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1213. AVI->track[AVI->aptr].mp3rate = bitrate;
  1214. return 0;
  1215. }
  1216. long AVI_read_frame(avi_t *AVI, char *vidbuf, int *keyframe)
  1217. {
  1218. long n;
  1219. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1220. if(!AVI->video_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1221. if(AVI->video_pos < 0 || AVI->video_pos >= AVI->video_frames) return -1;
  1222. n = AVI->video_index[AVI->video_pos].len;
  1223. *keyframe = (AVI->video_index[AVI->video_pos].key==0x10) ? 1:0;
  1224. lseek(AVI->fdes, AVI->video_index[AVI->video_pos].pos, SEEK_SET);
  1225. if (avi_read(AVI->fdes,vidbuf,n) != n)
  1226. {
  1227. AVI_errno = AVI_ERR_READ;
  1228. return -1;
  1229. }
  1230. AVI->video_pos++;
  1231. return n;
  1232. }
  1233. int AVI_set_audio_position(avi_t *AVI, long byte)
  1234. {
  1235. long n0, n1, n;
  1236. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1237. if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1238. if(byte < 0) byte = 0;
  1239. /* Binary search in the audio chunks */
  1240. n0 = 0;
  1241. n1 = AVI->track[AVI->aptr].audio_chunks;
  1242. while(n0<n1-1)
  1243. {
  1244. n = (n0+n1)/2;
  1245. if(AVI->track[AVI->aptr].audio_index[n].tot>byte)
  1246. n1 = n;
  1247. else
  1248. n0 = n;
  1249. }
  1250. AVI->track[AVI->aptr].audio_posc = n0;
  1251. AVI->track[AVI->aptr].audio_posb = byte - AVI->track[AVI->aptr].audio_index[n0].tot;
  1252. return 0;
  1253. }
  1254. long AVI_read_audio(avi_t *AVI, char *audbuf, long bytes)
  1255. {
  1256. long nr, pos, left, todo;
  1257. if(AVI->mode==AVI_MODE_WRITE) { AVI_errno = AVI_ERR_NOT_PERM; return -1; }
  1258. if(!AVI->track[AVI->aptr].audio_index) { AVI_errno = AVI_ERR_NO_IDX; return -1; }
  1259. nr = 0; /* total number of bytes read */
  1260. while(bytes>0)
  1261. {
  1262. left = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].len - AVI->track[AVI->aptr].audio_posb;
  1263. if(left==0)
  1264. {
  1265. if(AVI->track[AVI->aptr].audio_posc>=AVI->track[AVI->aptr].audio_chunks-1) return nr;
  1266. AVI->track[AVI->aptr].audio_posc++;
  1267. AVI->track[AVI->aptr].audio_posb = 0;
  1268. continue;
  1269. }
  1270. if(bytes<left)
  1271. todo = bytes;
  1272. else
  1273. todo = left;
  1274. pos = AVI->track[AVI->aptr].audio_index[AVI->track[AVI->aptr].audio_posc].pos + AVI->track[AVI->aptr].audio_posb;
  1275. lseek(AVI->fdes, pos, SEEK_SET);
  1276. if (avi_read(AVI->fdes,audbuf+nr,todo) != todo)
  1277. {
  1278. AVI_errno = AVI_ERR_READ;
  1279. return -1;
  1280. }
  1281. bytes -= todo;
  1282. nr += todo;
  1283. AVI->track[AVI->aptr].audio_posb += todo;
  1284. }
  1285. return nr;
  1286. }
  1287. /* AVI_read_data: Special routine for reading the next audio or video chunk
  1288. without having an index of the file. */
  1289. int AVI_read_data(avi_t *AVI, char *vidbuf, long max_vidbuf,
  1290. char *audbuf, long max_audbuf,
  1291. long *len)
  1292. {
  1293. /*
  1294. * Return codes:
  1295. *
  1296. * 1 = video data read
  1297. * 2 = audio data read
  1298. * 0 = reached EOF
  1299. * -1 = video buffer too small
  1300. * -2 = audio buffer too small
  1301. */
  1302. int n;
  1303. char data[8];
  1304. if(AVI->mode==AVI_MODE_WRITE) return 0;
  1305. while(1)
  1306. {
  1307. /* Read tag and length */
  1308. if( avi_read(AVI->fdes,data,8) != 8 ) return 0;
  1309. /* if we got a list tag, ignore it */
  1310. if(strncasecmp(data,"LIST",4) == 0)
  1311. {
  1312. lseek(AVI->fdes,4,SEEK_CUR);
  1313. continue;
  1314. }
  1315. n = PAD_EVEN(str2ulong((unsigned char *)data+4));
  1316. if(strncasecmp(data,AVI->video_tag,3) == 0)
  1317. {
  1318. *len = n;
  1319. AVI->video_pos++;
  1320. if(n>max_vidbuf)
  1321. {
  1322. lseek(AVI->fdes,n,SEEK_CUR);
  1323. return -1;
  1324. }
  1325. if(avi_read(AVI->fdes,vidbuf,n) != n ) return 0;
  1326. return 1;
  1327. }
  1328. else if(strncasecmp(data,AVI->track[AVI->aptr].audio_tag,4) == 0)
  1329. {
  1330. *len = n;
  1331. if(n>max_audbuf)
  1332. {
  1333. lseek(AVI->fdes,n,SEEK_CUR);
  1334. return -2;
  1335. }
  1336. if(avi_read(AVI->fdes,audbuf,n) != n ) return 0;
  1337. return 2;
  1338. break;
  1339. }
  1340. else
  1341. if(lseek(AVI->fdes,n,SEEK_CUR)<0) return 0;
  1342. }
  1343. }
  1344. /* AVI_print_error: Print most recent error (similar to perror) */
  1345. char *(avi_errors[]) =
  1346. {
  1347. /* 0 */ "avilib - No Error",
  1348. /* 1 */ "avilib - AVI file size limit reached",
  1349. /* 2 */ "avilib - Error opening AVI file",
  1350. /* 3 */ "avilib - Error reading from AVI file",
  1351. /* 4 */ "avilib - Error writing to AVI file",
  1352. /* 5 */ "avilib - Error writing index (file may still be useable)",
  1353. /* 6 */ "avilib - Error closing AVI file",
  1354. /* 7 */ "avilib - Operation (read/write) not permitted",
  1355. /* 8 */ "avilib - Out of memory (malloc failed)",
  1356. /* 9 */ "avilib - Not an AVI file",
  1357. /* 10 */ "avilib - AVI file has no header list (corrupted?)",
  1358. /* 11 */ "avilib - AVI file has no MOVI list (corrupted?)",
  1359. /* 12 */ "avilib - AVI file has no video data",
  1360. /* 13 */ "avilib - operation needs an index",
  1361. /* 14 */ "avilib - Unkown Error"
  1362. };
  1363. static int num_avi_errors = sizeof(avi_errors)/sizeof(char*);
  1364. static char error_string[4096];
  1365. void AVI_print_error(char *str)
  1366. {
  1367. int aerrno;
  1368. aerrno = (AVI_errno>=0 && AVI_errno<num_avi_errors) ? AVI_errno : num_avi_errors-1;
  1369. fprintf(stderr,"%s: %s\n",str,avi_errors[aerrno]);
  1370. /* for the following errors, perror should report a more detailed reason: */
  1371. if(AVI_errno == AVI_ERR_OPEN ||
  1372. AVI_errno == AVI_ERR_READ ||
  1373. AVI_errno == AVI_ERR_WRITE ||
  1374. AVI_errno == AVI_ERR_WRITE_INDEX ||
  1375. AVI_errno == AVI_ERR_CLOSE )
  1376. {
  1377. perror("REASON");
  1378. }
  1379. }
  1380. char *AVI_strerror()
  1381. {
  1382. int aerrno;
  1383. aerrno = (AVI_errno>=0 && AVI_errno<num_avi_errors) ? AVI_errno : num_avi_errors-1;
  1384. if(AVI_errno == AVI_ERR_OPEN ||
  1385. AVI_errno == AVI_ERR_READ ||
  1386. AVI_errno == AVI_ERR_WRITE ||
  1387. AVI_errno == AVI_ERR_WRITE_INDEX ||
  1388. AVI_errno == AVI_ERR_CLOSE )
  1389. {
  1390. sprintf(error_string,"%s - %s",avi_errors[aerrno],strerror(errno));
  1391. return error_string;
  1392. }
  1393. else
  1394. {
  1395. return avi_errors[aerrno];
  1396. }
  1397. }
  1398. uint64_t AVI_max_size()
  1399. {
  1400. return((uint64_t) AVI_MAX_LEN);
  1401. }