avi.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:40k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*****************************************************************************
  2.  *
  3.  * This program is free software ; you can redistribute it and/or modify
  4.  * it under the terms of the GNU General Public License as published by
  5.  * the Free Software Foundation; either version 2 of the License, or
  6.  * (at your option) any later version.
  7.  *
  8.  * This program is distributed in the hope that it will be useful,
  9.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11.  * GNU General Public License for more details.
  12.  *
  13.  * You should have received a copy of the GNU General Public License
  14.  * along with this program; if not, write to the Free Software
  15.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
  16.  *
  17.  * $Id: avi.c 607 2006-01-22 20:58:29Z picard $
  18.  *
  19.  * The Core Pocket Media Player
  20.  * Copyright (c) 2004-2005 Gabor Kovacs
  21.  *
  22.  ****************************************************************************/
  23. #include "../common/common.h"
  24. #include "avi.h"
  25. #define INDEXSTEP 512
  26. #define AVI_INDEX_OF_INDEXES 0x00
  27. #define AVI_INDEX_OF_CHUNKS 0x01
  28. #define AVI_INDEX_KEY 0x80000000
  29. typedef struct aviindex
  30. {
  31. int32_t Id;
  32. int8_t Flags[4];
  33. int32_t Pos;
  34. int32_t Length;
  35. } aviindex;
  36. typedef struct avisuperindex
  37. {
  38. int Offset;
  39. int Size;
  40. int StartTime;
  41. int EndTime;
  42. int LastData;
  43. } avisuperindex;
  44. typedef struct avistdindex
  45. {
  46. uint32_t FourCC;
  47. int Size;
  48. int16_t LongsPerEntry;
  49. int8_t IndexSubType;
  50. int8_t IndexType;
  51. int Count;
  52. int ChunkId;
  53. int OffsetLow;
  54. int OffsetHigh;
  55. int Reserved;
  56. } avistdindex;
  57. typedef struct avistream
  58. {
  59. format_stream Stream;
  60. int* Index; // mediatime
  61. bool_t ByteRate;
  62. int RefStart;
  63. int MediaTime;
  64. int NewMediaTime; // after seek (if seek successed)
  65. fraction64 MediaRate; // byterate or packetrate
  66. int SampleSize;
  67. int MaxPacket;
  68. int Length;
  69. int SuperIndexCount;
  70. avisuperindex* SuperIndex; //opendml index
  71. int PrevKey;
  72. int PrevMediaTime;
  73. int PrevKeyBuffer;
  74. filepos_t OffsetMin;
  75. filepos_t OffsetMax;
  76. int* ZeroChunkPos;
  77. array ZeroChunk;
  78. int LastPos;
  79. } avistream;
  80. typedef struct avi
  81. {
  82. format_base Format;
  83. int FramePeriod;
  84. int ByteRate;
  85. bool_t ErrorIndex;
  86. bool_t UnLimited;
  87. bool_t CheckForZero;
  88. bool_t FoundStdIndex;
  89. int DataPos;
  90. int DataEnd;
  91. // stream header and format loading
  92. int HeadType;
  93. avistream* LastStream;
  94. int VideoHandler;
  95. int VideoFrames;
  96. fraction VideoFPS;
  97. int VideoStart;
  98. fraction AudioRate;
  99. int AudioLength;
  100. int AudioStart;
  101. int AudioSampleSize;
  102. int IndexAdjustPos;
  103. int IndexCount;
  104. int IndexPos;
  105. int IndexReaded;
  106. int IndexBufferNo;
  107. block IndexBuffer;
  108. char NameChar[256];
  109. int FoundTotal;
  110. int FoundAtEnd[8];
  111. int FoundLastPos[8];
  112. } avi;
  113. #define ALIGN2(x) (((x)+1)&~1)
  114. #define ISDIGIT(x) ((x)>='0' && (x)<='9')
  115. #define STREAMNO(x) ((((x) & 255)-'0')*10 + ((((x) >> 8) & 255)-'0'))
  116. #define ISDATA(x) (ISDIGIT((x) & 255) && ISDIGIT(((x) >> 8) & 255))
  117. #define ISIDX(x) (ISDIGIT(((x) >> 16) & 255) && ISDIGIT(((x) >> 24) & 255) && ((x) & 255)=='i' && (((x) >> 8) & 255)=='x')
  118. #define IDXNO(x) (((((x) >> 16) & 255)-'0')*10 + ((((x) >> 24) & 255)-'0'))
  119. static void Done(avi* p)
  120. {
  121. FreeBlock(&p->IndexBuffer);
  122. }
  123. #define CHECKINDEX 16384
  124. static NOINLINE int Load32LE(const uint8_t* i) { return LOAD32LE(i); }
  125. static void PreCheckIndexODML(avi* p,avistream* Stream)
  126. {
  127. int k;
  128. array Array = {NULL};
  129. avistdindex StdIndex;
  130. stream* Input = p->Format.Reader->Input;
  131. filepos_t Save = Input->Seek(Input,0,SEEK_CUR);
  132. if (Save>=0 && Input->Seek(Input,Stream->SuperIndex[0].Offset,SEEK_SET)>=0)
  133. {
  134. if (Input->Read(Input,&StdIndex,sizeof(StdIndex)) == sizeof(StdIndex) &&
  135. StdIndex.IndexType == AVI_INDEX_OF_CHUNKS &&
  136. StdIndex.LongsPerEntry == 2)
  137. {
  138. if (StdIndex.Count > 1024)
  139. StdIndex.Count = 1024;
  140. if (ArrayAppend(&Array,NULL,8*StdIndex.Count,1024))
  141. {
  142. if (Input->Read(Input,ARRAYBEGIN(Array,int32_t),8*StdIndex.Count) == 8*StdIndex.Count)
  143. {
  144. for (k=0;k<StdIndex.Count;++k)
  145. if ((ARRAYBEGIN(Array,int32_t)[k*2+1] & ~AVI_INDEX_KEY)==0)
  146. {
  147. p->CheckForZero = 1;
  148. break;
  149. }
  150. }
  151. ArrayClear(&Array);
  152. }
  153. }
  154. Input->Seek(Input,Save,SEEK_SET);
  155. }
  156. }
  157. static void PreCheckIndex(avi* p)
  158. {
  159. block Buffer;
  160. if (AllocBlock(CHECKINDEX,&Buffer,0,HEAP_ANY))
  161. {
  162. format_reader* Reader = p->Format.Reader;
  163. filepos_t Save = Reader->Input->Seek(Reader->Input,0,SEEK_CUR);
  164. if (Save>=0 && Reader->Input->Seek(Reader->Input,-CHECKINDEX,SEEK_END)>=0)
  165. {
  166. if (Reader->Input->ReadBlock(Reader->Input,&Buffer,0,CHECKINDEX)==CHECKINDEX)
  167. {
  168. int Type = 0;
  169. int LastNo;
  170. int No = 24;
  171. const uint8_t* i = Buffer.Ptr+CHECKINDEX-12;
  172. while (--i>=Buffer.Ptr+16)
  173. {
  174. if (p->NameChar[*i])
  175. {
  176. Type |= *i << No;
  177. No -= 8;
  178. if (No<0)
  179. {
  180. if (Type == FOURCCLE('J','U','N','K') && ISDATA(Load32LE(i-16)))
  181. {
  182. i -= 16;
  183. p->FoundStdIndex = 1;
  184. break;
  185. }
  186. if (ISDATA(Type) && (Load32LE(i+4) & ~0x10)==0)
  187. {
  188. p->FoundStdIndex = 1;
  189. break;
  190. }
  191. Type <<= 8;
  192. No += 8;
  193. }
  194. }
  195. else
  196. {
  197. Type = 0;
  198. No = 24;
  199. }
  200. }
  201. LastNo = -1;
  202. for (;i>=Buffer.Ptr+16;i-=16)
  203. {
  204. if (Load32LE(i-8) == FOURCCLE('i','d','x','1'))
  205. break;
  206. Type = Load32LE(i);
  207. if (ISDATA(Type))
  208. {
  209. int Pos = Load32LE(i+8);
  210. int No = STREAMNO(Type);
  211. if (No >= 0 && No < 8)
  212. {
  213. if (No != LastNo)
  214. {
  215. if (LastNo>=0)
  216. ++p->FoundAtEnd[LastNo];
  217. LastNo = No;
  218. }
  219. if (p->FoundLastPos[No] == Pos)
  220. p->CheckForZero = 1;
  221. p->FoundLastPos[No] = Pos;
  222. ++p->FoundTotal;
  223. }
  224. if (Load32LE(i+12)==0 && Pos==Load32LE(i-16+8))
  225. {
  226. p->CheckForZero = 1;
  227. break;
  228. }
  229. }
  230. }
  231. if (LastNo>=0)
  232. ++p->FoundAtEnd[LastNo];
  233. }
  234. Reader->Input->Seek(Reader->Input,Save,SEEK_SET);
  235. }
  236. FreeBlock(&Buffer);
  237. }
  238. }
  239. static int Init(avi* p)
  240. {
  241. int DataLength;
  242. int Type;
  243. format_reader* Reader = p->Format.Reader;
  244. if (!AllocBlock(sizeof(aviindex)*INDEXSTEP,&p->IndexBuffer,0,HEAP_ANY))
  245. return ERR_OUT_OF_MEMORY;
  246. memset(p->FoundAtEnd,0,sizeof(p->FoundAtEnd));
  247. memset(p->FoundLastPos,0,sizeof(p->FoundLastPos));
  248. p->LastStream = NULL;
  249. p->FoundTotal = 0;
  250. p->FoundStdIndex = 0;
  251. p->CheckForZero = 0;
  252. p->UnLimited = 1;
  253. p->IndexAdjustPos = 4;
  254. p->IndexPos = -1;
  255. p->IndexCount = 0;
  256. p->IndexReaded = 0;
  257. p->IndexBufferNo = -1;
  258. p->DataPos = -1;
  259. p->DataEnd = -1;
  260. p->ErrorIndex = 0;
  261. p->AudioLength = 0;
  262. memset(p->NameChar,0,sizeof(p->NameChar));
  263. memset(p->NameChar+'a',1,'z'-'a');
  264. memset(p->NameChar+'A',1,'Z'-'A');
  265. memset(p->NameChar+'0',1,'9'-'0');
  266. p->NameChar['_']=1;
  267. p->NameChar[' ']=1;
  268. Type = Reader->ReadLE32(Reader);
  269. DataLength = Reader->ReadLE32(Reader);
  270. if (Type != FOURCCLE('R','I','F','F'))
  271. return ERR_INVALID_DATA;
  272. if (DataLength > 256 && (p->Format.FileSize < 0 || p->Format.FileSize > DataLength + 8))
  273. p->Format.FileSize = DataLength + 8;
  274. Reader->ReadLE32(Reader); // 'AVI ' or 'AVIX'
  275. PreCheckIndex(p);
  276. return ERR_NONE;
  277. }
  278. static INLINE int ChunkTime(avistream* Stream, int DataLength)
  279. {
  280. if (Stream->ByteRate)
  281. return DataLength; //byterate
  282. // packetrate
  283. if (DataLength > Stream->MaxPacket) 
  284. return (DataLength + Stream->MaxPacket - 1) / Stream->MaxPacket;
  285. return 1;
  286. }
  287. static void UpdateAviFrameRate(avi* p)
  288. {
  289. if (QueryAdvanced(ADVANCED_AVIFRAMERATE) && p->AudioLength && p->VideoFrames)
  290. {
  291. int i;
  292. for (i=0;i<p->Format.StreamCount;++i)
  293. {
  294. avistream* Stream = (avistream*) p->Format.Streams[i];
  295. if (Stream->Stream.Format.Type == PACKET_VIDEO && Stream->Length)
  296. {
  297. Stream->MediaRate.Num = Scale64(p->AudioLength,(int64_t)p->AudioRate.Den*TICKSPERSEC,p->AudioRate.Num);
  298. Stream->MediaRate.Den = p->VideoFrames;
  299. }
  300. }
  301. }
  302. }
  303. static bool_t SubtitleTiming(format_packet* Packet,format_reader* Reader,int Length)
  304. {
  305. int Hour0,Hour1,Min0,Min1,Sec0,Sec1,MSec0,MSec1;
  306. int i;
  307. tchar_t s[64];
  308. for (i=0;i<63 && Length>0;++i)
  309. {
  310. int ch = Reader->Read8(Reader);
  311. --Length;
  312. if (ch<0 || ch==']') break;
  313. s[i] = (tchar_t)ch;
  314. }
  315. s[i] = 0;
  316. if (stscanf(s,T("[%d:%d:%d.%d-%d:%d:%d.%d"),&Hour0,&Min0,&Sec0,&MSec0,&Hour1,&Min1,&Sec1,&MSec1)!=8)
  317. {
  318. Reader->Skip(Reader,Length);
  319. return 0;
  320. }
  321. Packet->RefTime = Scale(((Hour0*60+Min0)*60+Sec0)*1000+MSec0,TICKSPERSEC,1000);
  322. Packet->EndRefTime = Scale(((Hour1*60+Min1)*60+Sec1)*1000+MSec1,TICKSPERSEC,1000);
  323. Packet->Data = Reader->ReadAsRef(Reader,Length);
  324. return 1;
  325. }
  326. static void SetMediaTime(avistream* p,int Time)
  327. {
  328. p->MediaTime = Time;
  329. p->ZeroChunkPos = ARRAYBEGIN(p->ZeroChunk,int);
  330. if (p->ZeroChunkPos)
  331. while (*p->ZeroChunkPos < Time)
  332. ++p->ZeroChunkPos;
  333. }
  334. static void ReadMeta(avi* p, format_reader* Reader, int* DataLength)
  335. {
  336. pin* Comment = &p->LastStream->Stream.Comment;
  337. tchar_t Meta[512];
  338. char UTF8[512];
  339. int Len = *DataLength;
  340. if (Len>=512) Len=511;
  341. Len = Reader->Read(Reader,UTF8,Len);
  342. if (Len>0)
  343. {
  344. *DataLength -= Len;
  345. UTF8[Len] = 0;
  346. tcscpy_s(Meta,TSIZEOF(Meta),T("LANGUAGE="));
  347. UTF8ToTcs(Meta+tcslen(Meta),TSIZEOF(Meta)-tcslen(Meta),UTF8);
  348. if (Comment->Node)
  349. Comment->Node->Set(Comment->Node,Comment->No,Meta,sizeof(Meta));
  350. }
  351. }
  352. static void CheckIndex(avi* p, format_reader* Reader);
  353. static int ReadPacket(avi* p, format_reader* Reader, format_packet* Packet)
  354. {
  355. avistream* Stream;
  356. int No,Ch,StartPos;
  357. int SubType,Type,DataLength;
  358. tick_t Duration;
  359. int LongsPerEntry;
  360. int IndexType;
  361. int Count;
  362. int BaseOffset;
  363. // find a valid chunk header first
  364. //DEBUG_MSG1(DEBUG_FORMAT,T("AVI Packet %08x"),Reader->FilePos);
  365. StartPos = Reader->FilePos;
  366. if (!p->UnLimited && p->DataEnd >= 0 && Reader->FilePos >= p->DataEnd)
  367. return ERR_END_OF_FILE;
  368. do
  369. {
  370. bool_t PossibleAlign = Reader->FilePos & 1;
  371. Type = 0;
  372. No = 0;
  373. while (No<32)
  374. {
  375. Ch = Reader->Read8(Reader);
  376. if (Ch>=0 && p->NameChar[Ch])
  377. {
  378. Type |= Ch << No;
  379. No += 8;
  380. if (No==32 && PossibleAlign)
  381. {
  382. int Stream = STREAMNO(Type);
  383. if (!ISDATA(Type) || ISDIGIT((Type>>16) & 255) || ISDIGIT((Type>>24) & 255) || 
  384. Stream <0 || Stream>=p->Format.StreamCount)
  385. {
  386. No -= 8;
  387. Type >>= 8;
  388. }
  389. }
  390. }
  391. else
  392. {
  393. if (!PossibleAlign)
  394. {
  395. Reader->OutOfSync = 1;
  396. if ((Reader->FilePos-StartPos)>=16384)
  397. return ERR_DATA_NOT_FOUND; // this will force the process loop to stop, so input thread can be woken up
  398. if (Reader->Eof(Reader))
  399. return ERR_END_OF_FILE;
  400. }
  401. No = 0;
  402. Type = 0;
  403. PossibleAlign = 0;
  404. }
  405. }
  406. if (!p->UnLimited && p->DataEnd >= 0 && Reader->FilePos >= p->DataEnd)
  407. return ERR_END_OF_FILE;
  408. DataLength = Reader->ReadLE32(Reader);
  409. if (DataLength<0 || (Reader->FilePos+DataLength<0) || (p->DataPos>=0 && p->Format.FileSize>=0 && Reader->FilePos+DataLength>p->Format.FileSize))
  410. {
  411. DataLength = -1;
  412. Reader->OutOfSync = 1;
  413. continue;
  414. }
  415. if (ISDATA(Type))
  416. {
  417. No = STREAMNO(Type);
  418. if (No >= 0 && No < p->Format.StreamCount)
  419. {
  420. //DEBUG_MSG3(-1,"AVI Packet stream:%d pos:%08x length:%d",No,Reader->FilePos,DataLength);
  421. Stream = (avistream*) p->Format.Streams[No];
  422. if (Stream->Stream.Reader != Reader)
  423. break;
  424. if (Reader->OutOfSync)
  425. {
  426. if (p->Format.ProcessTime >= 0)
  427. {
  428. int i;
  429. tick_t RefTime;
  430. // this won't solve the out of sync problem
  431. // but at least the streams won't be dropped
  432. for (i=0;i<p->Format.StreamCount;++i)
  433. {
  434. avistream* s = (avistream*) p->Format.Streams[i];
  435. if (s->Stream.Reader == Reader)
  436. {
  437. RefTime = s->RefStart+Scale64(s->MediaTime,s->MediaRate.Num,s->MediaRate.Den);
  438. if (RefTime < p->Format.ProcessTime - TICKSPERSEC)
  439. SetMediaTime(s,Scale64(p->Format.ProcessTime-s->RefStart,s->MediaRate.Den,s->MediaRate.Num));
  440. }
  441. }
  442. }
  443. Reader->OutOfSync = 0;
  444. }
  445. Packet->Stream = &Stream->Stream;
  446. if (Stream->ZeroChunkPos)
  447. while (*Stream->ZeroChunkPos == Stream->MediaTime)
  448. {
  449. Stream->MediaTime += ChunkTime(Stream,0);
  450. ++Stream->ZeroChunkPos;
  451. }
  452. if (Stream->Stream.Format.Type == PACKET_SUBTITLE)
  453. {
  454. if (!SubtitleTiming(Packet,Reader,DataLength))
  455. continue;
  456. }
  457. else
  458. {
  459. Packet->Data = Reader->ReadAsRef(Reader,DataLength);
  460. Packet->RefTime = Stream->RefStart+Scale64(Stream->MediaTime,Stream->MediaRate.Num,Stream->MediaRate.Den);
  461. }
  462. DEBUG_MSG5(DEBUG_FORMAT,T("AVI stream:%d time:%d mediatime:%d pos:%08x length:%08x"),No,Packet->RefTime,Stream->MediaTime,Reader->FilePos,DataLength);
  463. Stream->MediaTime += ChunkTime(Stream,DataLength);
  464. return ERR_NONE;
  465. }
  466. }
  467. if (ISIDX(Type))
  468. {
  469. No = IDXNO(Type);
  470. if (No >= 0 && No < p->Format.StreamCount)
  471. break; // opendml index
  472. }
  473. switch (Type)
  474. {
  475. case FOURCCLE('R','I','F','F'):
  476. Reader->ReadLE32(Reader); // 'AVI ' or 'AVIX'
  477. return ERR_NONE;
  478. case FOURCCLE('a','v','i','h'):
  479. if (p->Format.HeaderLoaded) break;
  480. p->FramePeriod = Reader->ReadLE32(Reader);
  481. p->ByteRate = Reader->ReadLE32(Reader);
  482. DataLength -= 8;
  483. break;
  484. case FOURCCLE('i','n','d','x'):
  485. if (p->Format.HeaderLoaded) break;
  486. // opendml index
  487. LongsPerEntry = Reader->ReadLE16(Reader);
  488. Reader->Read8(Reader); //subtype
  489. IndexType = Reader->Read8(Reader);
  490. Count = Reader->ReadLE32(Reader);
  491. Type = Reader->ReadLE32(Reader);
  492. BaseOffset = (int)Reader->ReadLE64(Reader);
  493. Reader->Skip(Reader,4);
  494. DataLength -= 6*4;
  495. if (ISDATA(Type))
  496. {
  497. No = STREAMNO(Type);
  498. if (No >= 0 && No < p->Format.StreamCount && Count)
  499. {
  500. avisuperindex* s;
  501. Stream = (avistream*) p->Format.Streams[No];
  502. if (IndexType == AVI_INDEX_OF_CHUNKS && LongsPerEntry==2)
  503. {
  504. p->UnLimited = 1;
  505. p->Format.FileSize = -1;
  506. // create fake index of indexes
  507. Stream->SuperIndexCount = 1;
  508. Stream->SuperIndex = s = (avisuperindex*) malloc(sizeof(avisuperindex));
  509. s->Offset = Reader->FilePos - 6*4 - 8;
  510. s->Size = DataLength + 6*4 + 8;
  511. s->StartTime = 0;
  512. s->EndTime = 0;
  513. s->LastData = 0;
  514. for (No=0;No<Count;++No)
  515. {
  516. int Data = BaseOffset + Reader->ReadLE32(Reader) - 8;
  517. int Size = Reader->ReadLE32(Reader) & ~AVI_INDEX_KEY;
  518. if (s->LastData < Data)
  519. s->LastData = Data;
  520. s->EndTime += ChunkTime(Stream,Size);
  521. }
  522. }
  523. if (IndexType == AVI_INDEX_OF_INDEXES && LongsPerEntry==4)
  524. {
  525. int Time;
  526. p->UnLimited = 1;
  527. p->Format.FileSize = -1;
  528. // load index of indexes
  529. Stream->SuperIndexCount = Count;
  530. Stream->SuperIndex = s = (avisuperindex*) malloc(sizeof(avisuperindex)*Count);
  531. Time = 0;
  532. for (No=0;No<Count;++No,++s)
  533. {
  534. s->Offset = (int)Reader->ReadLE64(Reader);
  535. s->Size = Reader->ReadLE32(Reader);
  536. s->StartTime = Time;
  537. Time += Reader->ReadLE32(Reader) * Stream->SampleSize;
  538.    s->EndTime = Time;
  539. s->LastData = -1;
  540. DataLength -= 16;
  541. }
  542. if (Count && !p->FoundStdIndex && !p->CheckForZero && Stream->Stream.Format.Type == PACKET_VIDEO)
  543. {
  544. LockEnter(p->Format.InputLock);
  545. PreCheckIndexODML(p,Stream);
  546. LockLeave(p->Format.InputLock);
  547. }
  548. }
  549. }
  550. }
  551. break;
  552. case FOURCCLE('s','t','r','h'):
  553. if (p->Format.HeaderLoaded) break;
  554. p->HeadType = Reader->ReadLE32(Reader);
  555. DataLength -= 4;
  556. if (p->HeadType == FOURCCLE('v','i','d','s'))
  557. {
  558. p->VideoHandler = Reader->ReadLE32(Reader);
  559. Reader->ReadLE32(Reader); // flags
  560. Reader->ReadLE16(Reader); // priority
  561. Reader->ReadLE16(Reader); // language
  562. Reader->ReadLE32(Reader); 
  563. p->VideoFPS.Den = Reader->ReadLE32(Reader); 
  564. p->VideoFPS.Num = Reader->ReadLE32(Reader); 
  565. if (!p->VideoFPS.Den || !p->VideoFPS.Num)
  566. {
  567. p->VideoFPS.Den = 1;
  568. p->VideoFPS.Num = 25;
  569. }
  570. if (p->VideoFPS.Den==1 && p->VideoFPS.Num >= 12000) //not important
  571. p->VideoFPS.Den = 1000;
  572. p->VideoStart = Reader->ReadLE32(Reader);
  573. p->VideoFrames = Reader->ReadLE32(Reader);
  574. DataLength -= 32;
  575. }
  576. else
  577. if (p->HeadType == FOURCCLE('a','u','d','s'))
  578. {
  579. Reader->ReadLE32(Reader); // format
  580. Reader->ReadLE32(Reader); // flags
  581. Reader->ReadLE16(Reader); // priority
  582. Reader->ReadLE16(Reader); // language
  583. Reader->ReadLE32(Reader); 
  584. p->AudioRate.Den = Reader->ReadLE32(Reader); 
  585. p->AudioRate.Num = Reader->ReadLE32(Reader); 
  586. p->AudioStart = Reader->ReadLE32(Reader);
  587. p->AudioLength = Reader->ReadLE32(Reader);
  588. Reader->ReadLE32(Reader); // initialframes
  589. Reader->ReadLE32(Reader); // suggested buffersize
  590. p->AudioSampleSize = Reader->ReadLE32(Reader);
  591. DataLength -= 44;
  592. }
  593. break;
  594. case FOURCCLE('s','t','r','n'):
  595. if (p->Format.HeaderLoaded) break;
  596. if (p->LastStream && DataLength)
  597. ReadMeta(p,Reader,&DataLength);
  598. break;
  599. case FOURCCLE('s','t','r','f'):
  600. if (p->Format.HeaderLoaded) break;
  601. if (p->HeadType == FOURCCLE('v','i','d','s'))
  602. {
  603. p->LastStream = Stream = (avistream*) Format_AddStream(&p->Format,sizeof(avistream));
  604. if (Stream)
  605. {
  606. Stream->Index = NULL;
  607. Stream->SuperIndex = NULL;
  608. Stream->ByteRate = 0;
  609. Stream->Stream.Fragmented = 0;
  610. Stream->SampleSize = 1;
  611. Stream->MaxPacket = MAX_INT;
  612. Format_BitmapInfo(Reader,&Stream->Stream,DataLength);
  613. if (Stream->Stream.Format.Format.Video.Pixel.FourCC == FOURCC('D','X','S','B'))
  614. {
  615. PacketFormatClear(&Stream->Stream.Format);
  616. Stream->Stream.Format.Type = PACKET_SUBTITLE;
  617. Stream->Stream.Format.Format.Subtitle.FourCC = FOURCC('D','X','S','B');
  618. }
  619. else
  620. {
  621. if (Stream->Stream.Format.Format.Video.Pixel.FourCC == 4)
  622. Stream->Stream.Format.Format.Video.Pixel.FourCC = UpperFourCC(p->VideoHandler);
  623. Stream->MediaRate.Den = p->VideoFPS.Num;
  624. Stream->MediaRate.Num = (int64_t)p->VideoFPS.Den * TICKSPERSEC;
  625. Stream->RefStart = Scale64(p->VideoStart,Stream->MediaRate.Num,Stream->MediaRate.Den);
  626. Stream->Length = p->VideoFrames;
  627. Stream->Stream.Format.PacketRate = p->VideoFPS;
  628. if (p->VideoFrames)
  629. {
  630. Duration = Scale64(p->VideoFrames,Stream->MediaRate.Num,Stream->MediaRate.Den);
  631. if (p->Format.Duration < Duration)
  632. p->Format.Duration = Duration;
  633. }
  634. UpdateAviFrameRate(p);
  635. }
  636. Format_PrepairStream(&p->Format,&Stream->Stream);
  637. }
  638. else
  639. Reader->Skip(Reader,DataLength);
  640. return ERR_NONE;
  641. }
  642. else
  643. if (p->HeadType == FOURCCLE('a','u','d','s'))
  644. {
  645. p->LastStream = Stream = (avistream*) Format_AddStream(&p->Format,sizeof(avistream));
  646. if (Stream)
  647. {
  648. Format_WaveFormat(Reader,&Stream->Stream,DataLength);
  649. // some encoders doesn't set AudioSampleSize, but still using CBR mode
  650. // detect it by insane packet rate
  651. if (!p->AudioSampleSize && p->AudioRate.Den*1000<=p->AudioRate.Num)
  652. p->AudioSampleSize = Stream->Stream.Format.Format.Audio.BlockAlign;
  653. Stream->Index = NULL;
  654. Stream->SuperIndex = NULL;
  655. Stream->ByteRate = p->AudioSampleSize != 0;
  656. Stream->Stream.Fragmented = Stream->ByteRate && p->AudioSampleSize <= 4;
  657. if (!Stream->ByteRate)
  658. {
  659. // VBR (packetrate)
  660. Stream->MediaRate.Den = p->AudioRate.Num;
  661. Stream->MediaRate.Num = (int64_t)p->AudioRate.Den * TICKSPERSEC;
  662. if (p->AudioRate.Num == Stream->Stream.Format.Format.Audio.SampleRate)
  663. Stream->MaxPacket = p->AudioRate.Den;
  664. else
  665. Stream->MaxPacket = MAX_INT;
  666. Stream->SampleSize = 1;
  667. }
  668. else
  669. {
  670. // CBR (byterate)
  671. // some digital cameras don't fill AudioSampleSize correctly only BlockAlign (with ADPCM)
  672. if (p->AudioSampleSize < Stream->Stream.Format.Format.Audio.BlockAlign)
  673. p->AudioSampleSize = Stream->Stream.Format.Format.Audio.BlockAlign;
  674. if (Stream->Stream.Format.Format.Audio.Format == 0x55 /*MP3*/ && 
  675. p->AudioRate.Num == 4977)
  676. {
  677. Stream->MediaRate.Den = (p->AudioRate.Num*16-7)*p->AudioSampleSize;
  678. Stream->MediaRate.Num = (int64_t)p->AudioRate.Den*TICKSPERSEC*16;
  679. }
  680. else
  681. {
  682. Stream->MediaRate.Den = p->AudioRate.Num*p->AudioSampleSize;
  683. Stream->MediaRate.Num = (int64_t)p->AudioRate.Den*TICKSPERSEC;
  684. }
  685. Stream->SampleSize = p->AudioSampleSize;
  686. }
  687. Stream->RefStart = Scale64(p->AudioStart,(int64_t)p->AudioRate.Den*TICKSPERSEC,p->AudioRate.Num);
  688. Stream->Length = p->AudioLength;
  689. if (p->AudioLength)
  690. {
  691. Duration = Scale64(p->AudioLength,(int64_t)p->AudioRate.Den*TICKSPERSEC,p->AudioRate.Num);
  692. if (Duration>0 && p->Format.Duration < Duration)
  693. p->Format.Duration = Duration;
  694. }
  695. UpdateAviFrameRate(p);
  696. Format_PrepairStream(&p->Format,&Stream->Stream);
  697. }
  698. else
  699. Reader->Skip(Reader,DataLength);
  700. return ERR_NONE;
  701. }
  702. else
  703. p->LastStream = NULL;
  704. break;
  705. case FOURCCLE('L','I','S','T'):
  706. SubType = Reader->ReadLE32(Reader);
  707. DataLength -= 4;
  708. switch (SubType)
  709. {
  710. case FOURCCLE('s','t','r','l'):
  711. return ERR_NONE;
  712. case FOURCCLE('h','d','r','l'):
  713. return ERR_NONE;
  714. case FOURCCLE('m','o','v','i'):
  715. if (p->Format.HeaderLoaded) return ERR_NONE;
  716. p->DataPos = Reader->FilePos;
  717. p->DataEnd = DataLength + Reader->FilePos;
  718. p->Format.HeaderLoaded = 1;
  719. if (p->FoundTotal >= 256 && p->Format.StreamCount>1)
  720. {
  721. for (No=0;No<p->Format.StreamCount && No<8;++No)
  722. if (p->FoundAtEnd[No] < 2)
  723. p->CheckForZero = 1; // possibly non interleaved streams
  724. }
  725. if (p->CheckForZero)
  726. {
  727. LockEnter(p->Format.InputLock);
  728. CheckIndex(p,Reader);
  729. LockLeave(p->Format.InputLock);
  730. }
  731. for (No=0;No<p->Format.StreamCount;++No)
  732. SetMediaTime((avistream*)p->Format.Streams[No],0);
  733. return ERR_NONE;
  734. case FOURCCLE('o','d','m','l'):
  735. break;
  736. default:
  737. return ERR_NONE;
  738. }
  739. break;
  740. case FOURCCLE('J','U','N','K'):
  741. case FOURCCLE('i','d','x','1'):
  742. break;
  743. default: 
  744. if (Reader->OutOfSync || DataLength > 256*1024) // unknown
  745. DataLength = -1;
  746. }
  747. }
  748. while (DataLength<0);
  749. Reader->Skip(Reader,DataLength);
  750. return ERR_NONE;
  751. }
  752. static int ErrorIndex(avi* p,stream* Input,filepos_t OldFilePos)
  753. {
  754. if (OldFilePos>=0)
  755. {
  756. if (Input)
  757. Input->Seek(Input,OldFilePos,SEEK_SET);
  758. if (!p->ErrorIndex)
  759. {
  760. p->ErrorIndex = 1;
  761. ShowError(p->Format.Format.Class,AVI_ID,AVI_NO_INDEX);
  762. }
  763. }
  764. return ERR_NOT_SUPPORTED;
  765. }
  766. static INLINE const aviindex* IndexBuffer(avi* p,int n)
  767. {
  768. return ((const aviindex*)p->IndexBuffer.Ptr)+n;
  769. }
  770. static int LoadIndexBuffer(avi* p,stream* Input,int No,filepos_t OldFilePos)
  771. {
  772. if (p->IndexBufferNo != No)
  773. {
  774. int Bytes = (p->IndexCount - No*INDEXSTEP)*sizeof(aviindex);
  775. if (Bytes > INDEXSTEP*sizeof(aviindex))
  776. Bytes = INDEXSTEP*sizeof(aviindex);
  777. if (Input->Seek(Input,p->IndexPos+No*INDEXSTEP*sizeof(aviindex),SEEK_SET)<0)
  778. return ErrorIndex(p,Input,OldFilePos);
  779. if (Input->ReadBlock(Input,&p->IndexBuffer,0,Bytes) != Bytes)
  780. return ErrorIndex(p,Input,OldFilePos);
  781. p->IndexBufferNo = No;
  782. if (No == 0)
  783. {
  784. if (INT32LE(IndexBuffer(p,0)->Pos) == p->DataPos)
  785. p->IndexAdjustPos = p->DataPos;
  786. else
  787. p->IndexAdjustPos = 4;
  788. }
  789. }
  790. return ERR_NONE;
  791. }
  792. static int ReadIndex(stream* Input,avistream* Stream,avisuperindex* Index,int MediaTime,int DstPos,bool_t PrevKey)
  793. {
  794. bool_t NeedKey = Stream->Stream.Format.Type == PACKET_VIDEO;
  795. avistdindex StdIndex;
  796. int No;
  797. int FoundPos = -1;
  798. int32_t* i; 
  799. int LookBack = 0;
  800. if (!NeedKey)
  801. PrevKey = 0;
  802. if (PrevKey)
  803. LookBack = 300;
  804. if (DstPos>=0 && Index->LastData>=0 && DstPos > Index->LastData)
  805. return -1;
  806. if (MediaTime>=0 && Index->EndTime + LookBack <= MediaTime)
  807. return -1;
  808. if (Input->Seek(Input,Index->Offset,SEEK_SET) < 0)
  809. return -2;
  810. if (Input->Read(Input,&StdIndex,sizeof(StdIndex)) != sizeof(StdIndex))
  811. return -1;
  812. if (StdIndex.IndexType != AVI_INDEX_OF_CHUNKS ||
  813. StdIndex.LongsPerEntry != 2)
  814. return -1;
  815. i = (int32_t*) malloc(8*StdIndex.Count);
  816. if (!i)
  817. return -1;
  818. if (Input->Read(Input,i,8*StdIndex.Count) != 8*StdIndex.Count)
  819. {
  820. free(i);
  821. return -1;
  822. }
  823. if (Index->LastData<0)
  824. {
  825. Index->LastData = 0;
  826. for (No=0;No<StdIndex.Count;++No)
  827. {
  828. int Data = StdIndex.OffsetLow + i[No*2] - 8;
  829. int Size = i[No*2+1] & ~AVI_INDEX_KEY;
  830. if (Size && Index->LastData < Data)
  831. Index->LastData = Data;
  832. }
  833. }
  834. Stream->NewMediaTime = Index->StartTime;
  835. for (No=0;No<StdIndex.Count;++No)
  836. {
  837. int Data = StdIndex.OffsetLow + i[No*2] - 8;
  838. int Size = i[No*2+1];
  839. if (MediaTime>=0)
  840. {
  841. if (Stream->NewMediaTime >= MediaTime && (!NeedKey || !(Size & AVI_INDEX_KEY))) 
  842. {
  843. if (PrevKey && Stream->NewMediaTime != MediaTime && Stream->PrevKey>=0)
  844. {
  845. Stream->NewMediaTime = Stream->PrevMediaTime;
  846. FoundPos = Stream->PrevKey; // use previous key
  847. }
  848. else
  849. FoundPos = Data; // found sample after mediatime
  850. break;
  851. }
  852. if (PrevKey && !(Size & AVI_INDEX_KEY))
  853. {
  854. Stream->PrevMediaTime = Stream->NewMediaTime;
  855. Stream->PrevKey = Data;
  856. }
  857. }
  858. if (DstPos>=0 && Data >= DstPos) 
  859. {
  860. FoundPos = Data; // found a sample after the destination position
  861. break; 
  862. }
  863. Stream->NewMediaTime = Stream->NewMediaTime + ChunkTime(Stream,Size & ~AVI_INDEX_KEY);
  864. }
  865. free(i);
  866. return FoundPos;
  867. }
  868. static int RestorePrevKey(avi* p,avistream* Stream,int No,int OldFilePos,int* Pos)
  869. {
  870. int i,j;
  871. avistream* s;
  872. if (Stream->PrevKeyBuffer != No)
  873. {
  874. int Result = LoadIndexBuffer(p,Stream->Stream.Reader->Input,Stream->PrevKeyBuffer,OldFilePos);
  875. if (Result != ERR_NONE)
  876. return Result;
  877. No = Stream->PrevKeyBuffer;
  878. }
  879. // restart this block and recalc NewMediaTime
  880. for (j=0;j<p->Format.StreamCount;++j)
  881. {
  882. s = (avistream*) p->Format.Streams[j];
  883. s->NewMediaTime = s->Index[No];
  884. }
  885. for (i=0;i<Stream->PrevKey;++i)
  886. {
  887. j = STREAMNO(IndexBuffer(p,i)->Id);
  888. if (j>=0 && j<p->Format.StreamCount)
  889. {
  890. s = (avistream*) p->Format.Streams[j];
  891. s->NewMediaTime += ChunkTime(s,IndexBuffer(p,i)->Length);
  892. }
  893. }
  894. *Pos = INT32LE(IndexBuffer(p,i)->Pos) - p->IndexAdjustPos;
  895. return ERR_NONE;
  896. }
  897. static int FindIndexPos(avi* p,stream* Input)
  898. {
  899. int OldFilePos = Input->Seek(Input,0,SEEK_CUR);
  900. int Pos = p->DataEnd;
  901. // try to find index block
  902. if (Input->Seek(Input,Pos,SEEK_SET) < 0)
  903. return ERR_NOT_SUPPORTED;
  904. for (;;)
  905. {
  906. int32_t Head[2];
  907. if (Pos & 1)
  908. {
  909. if (Input->Read(Input,Head,sizeof(Head)) != sizeof(Head))
  910. return ErrorIndex(p,Input,OldFilePos);
  911. Pos += sizeof(Head);
  912. if (Head[0] != FOURCC('i','d','x','1'))
  913. {
  914. memmove((char*)Head,(char*)Head+1,sizeof(Head)-1);
  915. if (Input->Read(Input,(char*)Head+sizeof(Head)-1,1) != 1)
  916. return ErrorIndex(p,Input,OldFilePos);
  917. ++Pos;
  918. }
  919. }
  920. else
  921. {
  922. if (Input->Read(Input,Head,sizeof(Head)) != sizeof(Head))
  923. return ErrorIndex(p,Input,OldFilePos);
  924. Pos += sizeof(Head);
  925. }
  926. if (Head[0] == FOURCC('i','d','x','1'))
  927. {
  928. int i,No;
  929. p->IndexCount = Head[1] / sizeof(aviindex);
  930. i = ((p->IndexCount + INDEXSTEP - 1) / INDEXSTEP) + 1;
  931. for (No=0;No<p->Format.StreamCount;++No)
  932. {
  933. avistream* s = (avistream*) p->Format.Streams[No];
  934. s->Index = (int*) malloc(sizeof(int)*i);
  935. if (!s->Index)
  936. return ERR_OUT_OF_MEMORY;
  937. s->Index[0] = 0;
  938. }
  939. p->IndexPos = Pos;
  940. p->IndexReaded = 0;
  941. break;
  942. }
  943. if (Head[1]<0 || (Pos+Head[1]<0))
  944. return ErrorIndex(p,Input,OldFilePos);
  945. Pos += Head[1];
  946. if (Input->Seek(Input,Pos,SEEK_SET) != Pos)
  947. return ErrorIndex(p,Input,OldFilePos);
  948. }
  949. return ERR_NONE;
  950. }
  951. static NOINLINE int CheckIndexBuffer(avi* p,stream* Input,int No,filepos_t OldFilePos,int IndexCount)
  952. {
  953. // load page and calc sum mediatime
  954. if (p->IndexReaded <= No)
  955. {
  956. int i,j;
  957. int Result = LoadIndexBuffer(p,Input,No,OldFilePos);
  958. if (Result != ERR_NONE)
  959. return Result;
  960. for (j=0;j<p->Format.StreamCount;++j)
  961. {
  962. avistream* s = (avistream*) p->Format.Streams[j];
  963. s->Index[No+1] = s->Index[No];
  964. }
  965. for (i=0;i<IndexCount;++i)
  966. {
  967. j = STREAMNO(IndexBuffer(p,i)->Id);
  968. if (j>=0 && j<p->Format.StreamCount)
  969. {
  970. avistream* s = (avistream*) p->Format.Streams[j];
  971. s->Index[No+1] += ChunkTime(s,INT32LE(IndexBuffer(p,i)->Length));
  972. }
  973. }
  974. p->IndexReaded = No+1;
  975. }
  976. return ERR_NONE;
  977. }
  978. static int Seek(avi* p, tick_t Time, filepos_t FilePos, bool_t PrevKey)
  979. {
  980. int Result = ERR_NONE;
  981. int RNo;
  982. if (p->DataPos < 0)
  983. {
  984. // no avi header yet, only seek to the beginning supported
  985. if (Time>0 || FilePos>0)
  986. return ERR_NOT_SUPPORTED;
  987. p->Format.Reader[0].OutOfSync = 0;
  988. return Format_Seek(&p->Format,0,SEEK_SET);
  989. }
  990. for (RNo=0;RNo<MAXREADER;++RNo)
  991. {
  992. filepos_t Pos = -1;
  993. avistream* Stream;
  994. avistream* s;
  995. int i,j,No;
  996. format_reader* Reader = &p->Format.Reader[RNo];
  997. stream* Input = Reader->Input;
  998. filepos_t OldReaderPos = Reader->FilePos;
  999. filepos_t OldFilePos;
  1000. if (!Input)
  1001. break;
  1002. OldFilePos = Input->Seek(Input,0,SEEK_CUR);
  1003. if (Time <= 0 && FilePos <= 0)
  1004. {
  1005. // seek to the beginning (no index needed for that)
  1006. Pos = Reader->OffsetMin<MAX_INT?Reader->OffsetMin:p->DataPos;
  1007. for (j=0;j<p->Format.StreamCount;++j)
  1008. if (p->Format.Streams[j]->Reader == Reader)
  1009. ((avistream*)p->Format.Streams[j])->NewMediaTime = 0;
  1010. }
  1011. else
  1012. {
  1013. Stream = (avistream*) Format_DefSyncStream(&p->Format,Reader);
  1014. if (Stream)
  1015. {
  1016. bool_t NeedKey = Stream->Stream.Format.Type == PACKET_VIDEO;
  1017. int MediaTime = Scale64(Time,Stream->MediaRate.Den,Stream->MediaRate.Num);
  1018. Stream->PrevKey = -1;
  1019. if (PrevKey)
  1020. ++MediaTime; // seek to same position even if there is rounding error
  1021. if (Stream->SuperIndex)
  1022. {
  1023. // using OpenDML index
  1024. if (MediaTime >= Stream->SuperIndex[Stream->SuperIndexCount-1].EndTime)
  1025. MediaTime = Stream->SuperIndex[Stream->SuperIndexCount-1].EndTime-1;
  1026. // find position by MediaTime
  1027. for (No=0;No<Stream->SuperIndexCount;++No)
  1028. {
  1029. Pos = ReadIndex(Input,Stream,Stream->SuperIndex+No,MediaTime,-1,PrevKey);
  1030. if (Pos == -2)
  1031. return ERR_NOT_SUPPORTED;
  1032. if (Pos >= 0)
  1033. break;
  1034. }
  1035. if (Pos<0)
  1036. {
  1037. if (PrevKey && Stream->PrevKey>=0)
  1038. {
  1039. Stream->NewMediaTime = Stream->PrevMediaTime;
  1040. Pos = Stream->PrevKey;
  1041. }
  1042. else
  1043. {
  1044. Stream->NewMediaTime = Stream->SuperIndex[Stream->SuperIndexCount-1].EndTime;
  1045. Pos = Stream->SuperIndex[Stream->SuperIndexCount-1].LastData;
  1046. if (Pos<0)
  1047. return ErrorIndex(p,Input,OldFilePos);
  1048. }
  1049. }
  1050. // calculate NewMediaTime for all other streams
  1051. for (j=0;j<p->Format.StreamCount;++j)
  1052. {
  1053. s = (avistream*) p->Format.Streams[j];
  1054. if (s->Stream.Reader==Reader && s != Stream)
  1055. {
  1056. // find position by Pos
  1057. for (No=0;No<s->SuperIndexCount;++No)
  1058. if (ReadIndex(Input,s,s->SuperIndex+No,-1,Pos,0) >= 0)
  1059. break;
  1060. if (No==s->SuperIndexCount)
  1061. s->NewMediaTime = s->SuperIndex[s->SuperIndexCount-1].EndTime;
  1062. }
  1063. }
  1064. }
  1065. else
  1066. {
  1067. int Next;
  1068. int IndexCount,IndexLeft;
  1069. tick_t LookBack = 0;
  1070. // do we have the index block?
  1071. if (p->IndexPos < 0)
  1072. {
  1073. Result = FindIndexPos(p,Input);
  1074. if (Result!=ERR_NONE)
  1075. return Result;
  1076. }
  1077. IndexLeft = p->IndexCount;
  1078. if (!NeedKey)
  1079. PrevKey = 0;
  1080. if (PrevKey)
  1081. LookBack = 300;
  1082. // find the index page
  1083. for (No=0;IndexLeft>0;++No,IndexLeft-=INDEXSTEP)
  1084. {
  1085. IndexCount = IndexLeft;
  1086. if (IndexCount > INDEXSTEP)
  1087. IndexCount = INDEXSTEP;
  1088. Result = CheckIndexBuffer(p,Input,No,OldFilePos,IndexCount);
  1089. if (Result != ERR_NONE)
  1090. return Result;
  1091. //DEBUG_MSG4(DEBUG_FORMAT,"AVI IndexBlock no:%d start:%d end:%d (target:%d)",No,Stream->Index[No],Stream->Index[No+1],MediaTime);
  1092. if (Stream->Index[No]!=Stream->Index[No+1] &&
  1093. (Stream->Index[No+1]+LookBack > MediaTime || IndexLeft<2*INDEXSTEP))
  1094. {
  1095. Result = LoadIndexBuffer(p,Input,No,OldFilePos);
  1096. if (Result != ERR_NONE)
  1097. return Result;
  1098. for (j=0;j<p->Format.StreamCount;++j)
  1099. {
  1100. s = (avistream*) p->Format.Streams[j];
  1101. if (s->Stream.Reader == Reader)
  1102. s->NewMediaTime = s->Index[No];
  1103. }
  1104. // find sub page position
  1105. for (i=0;i<IndexCount;++i)
  1106. {
  1107. j = STREAMNO(IndexBuffer(p,i)->Id);
  1108. if (j>=0 && j<p->Format.StreamCount && p->Format.Streams[j]->Reader==Reader)
  1109. {
  1110. s = (avistream*) p->Format.Streams[j];
  1111. Next = s->NewMediaTime + ChunkTime(s,IndexBuffer(p,i)->Length);
  1112. //DEBUG_MSG3(DEBUG_FORMAT,"AVI Index stream:%d pos:%d flag:%d",j,INT32LE(IndexBuffer(p,i)->Pos),IndexBuffer(p,i)->Flags[0]);
  1113. if (s==Stream)
  1114. {
  1115. Pos = INT32LE(IndexBuffer(p,i)->Pos) - p->IndexAdjustPos;
  1116. if (s->NewMediaTime >= MediaTime)
  1117. {
  1118. // only accept keyframes with valid position
  1119. if (Pos >= 0 && Pos < p->DataEnd - p->DataPos &&
  1120. (!NeedKey || (IndexBuffer(p,i)->Flags[0] & 0x10)))
  1121. {
  1122. if (PrevKey && s->NewMediaTime != MediaTime && Stream->PrevKey>=0)
  1123. {
  1124. Result = RestorePrevKey(p,Stream,No,OldFilePos,&Pos);
  1125. if (Result != ERR_NONE)
  1126. return Result;
  1127. }
  1128. break;
  1129. }
  1130. }
  1131. if (Pos >= 0 && Pos < p->DataEnd - p->DataPos &&
  1132. (IndexBuffer(p,i)->Flags[0] & 0x10))
  1133. {
  1134. Stream->PrevKey = i;
  1135. Stream->PrevKeyBuffer = No;
  1136. }
  1137. }
  1138. s->NewMediaTime = Next;
  1139. }
  1140. }
  1141. // found? 
  1142. if (i<IndexCount)
  1143. break;
  1144. }
  1145. }
  1146. if (IndexLeft <= 0)
  1147. {
  1148. if (Stream->PrevKey>=0)
  1149. {
  1150. Result = RestorePrevKey(p,Stream,No,OldFilePos,&Pos);
  1151. if (Result != ERR_NONE)
  1152. return Result;
  1153. }
  1154. else
  1155. {
  1156. // go to end
  1157. for (j=0;j<p->Format.StreamCount;++j)
  1158. {
  1159. s = (avistream*) p->Format.Streams[j];
  1160. s->NewMediaTime = s->Index[p->IndexReaded];
  1161. }
  1162. Pos = p->DataEnd - p->DataPos;
  1163. }
  1164. }
  1165. Pos += p->DataPos;
  1166. }
  1167. if (NeedKey && Stream->NewMediaTime >= 0) // use updated time with other Readers
  1168. Time = Scale64(Stream->NewMediaTime,Stream->MediaRate.Num,Stream->MediaRate.Den);
  1169. }
  1170. }
  1171. if (Pos>=0)
  1172. {
  1173. Reader->FilePos = -1; // force seek, because Input changed
  1174. if (Reader->Seek(Reader,Pos,SEEK_SET) != ERR_NONE)
  1175. {
  1176. Reader->FilePos = OldReaderPos;
  1177. // restore old input position
  1178. Input->Seek(Input,OldFilePos,SEEK_SET);
  1179. return ERR_NOT_SUPPORTED;
  1180. }
  1181. // set new positions
  1182. for (j=0;j<p->Format.StreamCount;++j)
  1183. if (p->Format.Streams[j]->Reader == Reader)
  1184. {
  1185. s = (avistream*) p->Format.Streams[j];
  1186. SetMediaTime(s,s->NewMediaTime);
  1187. }
  1188. Reader->OutOfSync = 0;
  1189. }
  1190. }
  1191. Format_AfterSeek(&p->Format);
  1192. return ERR_NONE;
  1193. }
  1194. static NOINLINE void AddZeroChunk(avistream* Stream)
  1195. {
  1196. ArrayAppend(&Stream->ZeroChunk,&Stream->NewMediaTime,sizeof(Stream->NewMediaTime),512);
  1197. }
  1198. static void CheckIndex(avi* p, format_reader* Reader)
  1199. {
  1200. bool_t FlushBuffers = 0;
  1201. avistream* Stream;
  1202. int i,j,k;
  1203. bool_t OpenDML = 0;
  1204. array Array = {NULL};
  1205. stream* Input = Reader->Input;
  1206. filepos_t OldFilePos = Input->Seek(Input,0,SEEK_CUR);
  1207. filepos_t OldReaderPos = Reader->FilePos;
  1208. if (OldFilePos<0)
  1209. return;
  1210. for (i=0;i<p->Format.StreamCount;++i)
  1211. {
  1212. Stream = (avistream*)p->Format.Streams[i];
  1213. Stream->NewMediaTime = 0;
  1214. Stream->OffsetMin = MAX_INT;
  1215. Stream->OffsetMax = 0;
  1216. Stream->LastPos = 0;
  1217. if (Stream->SuperIndex) // we need non video streams as well for offsetmin/max
  1218. {
  1219. OpenDML = 1;
  1220. for (j=0;j<Stream->SuperIndexCount;++j)
  1221. {
  1222. avistdindex StdIndex;
  1223. if (Input->Seek(Input,Stream->SuperIndex[j].Offset,SEEK_SET) < 0)
  1224. break;
  1225. if (Input->Read(Input,&StdIndex,sizeof(StdIndex)) != sizeof(StdIndex))
  1226. break;
  1227. if (StdIndex.IndexType != AVI_INDEX_OF_CHUNKS ||
  1228. StdIndex.LongsPerEntry != 2)
  1229. break;
  1230. ArrayDrop(&Array);
  1231. if (!ArrayAppend(&Array,NULL,8*StdIndex.Count,1024))
  1232. break;
  1233. if (Input->Read(Input,ARRAYBEGIN(Array,int32_t),8*StdIndex.Count) != 8*StdIndex.Count)
  1234. break;
  1235. for (k=0;k<StdIndex.Count;++k)
  1236. {
  1237. int Pos = StdIndex.OffsetLow + ARRAYBEGIN(Array,int32_t)[k*2] - 8;
  1238. int Size = ARRAYBEGIN(Array,int32_t)[k*2+1] & ~AVI_INDEX_KEY;
  1239. if (!Size)
  1240. AddZeroChunk(Stream);
  1241. else
  1242. {
  1243. if (Stream->OffsetMin>Pos)
  1244. Stream->OffsetMin=Pos;
  1245. if (Stream->OffsetMax<Pos)
  1246. Stream->OffsetMax=Pos;
  1247. }
  1248. Stream->NewMediaTime = Stream->NewMediaTime + ChunkTime(Stream,Size);
  1249. }
  1250. }
  1251. }
  1252. }
  1253. if (!OpenDML && (p->IndexPos>=0 || FindIndexPos(p,Input)==ERR_NONE))
  1254. {
  1255. int IndexLeft = p->IndexCount;
  1256. int IndexCount;
  1257. int LastPos = 0;
  1258. for (i=0;IndexLeft>0;++i,IndexLeft-=INDEXSTEP)
  1259. {
  1260. IndexCount = IndexLeft;
  1261. if (IndexCount > INDEXSTEP)
  1262. IndexCount = INDEXSTEP;
  1263. if (CheckIndexBuffer(p,Input,i,-1,IndexCount)==ERR_NONE && 
  1264. LoadIndexBuffer(p,Input,i,-1)==ERR_NONE)
  1265. {
  1266. for (k=0;k<IndexCount;++k)
  1267. {
  1268. j = STREAMNO(IndexBuffer(p,k)->Id);
  1269. if (j>=0 && j<p->Format.StreamCount)
  1270. {
  1271. int Pos = IndexBuffer(p,k)->Pos - p->IndexAdjustPos + p->DataPos;
  1272. int Size = IndexBuffer(p,k)->Length;
  1273. Stream = (avistream*) p->Format.Streams[j];
  1274. if ((Size==0 && Pos==LastPos) || (Pos==Stream->LastPos))
  1275. AddZeroChunk(Stream);
  1276. if (Size)
  1277. {
  1278. if (Stream->OffsetMin>Pos)
  1279. Stream->OffsetMin=Pos;
  1280. if (Stream->OffsetMax<Pos)
  1281. Stream->OffsetMax=Pos;
  1282. }
  1283. LastPos = Pos;
  1284. Stream->LastPos=Pos;
  1285. Stream->NewMediaTime = Stream->NewMediaTime + ChunkTime(Stream,Size);
  1286. }
  1287. }
  1288. }
  1289. }
  1290. }
  1291. for (i=0;i<p->Format.StreamCount;++i)
  1292. {
  1293. Stream = (avistream*)p->Format.Streams[i];
  1294. if (!ARRAYEMPTY(Stream->ZeroChunk))
  1295. {
  1296. Stream->NewMediaTime = MAX_INT;
  1297. AddZeroChunk(Stream);
  1298. }
  1299. if (Stream->OffsetMax)
  1300. {
  1301. format_reader* Reader = Format_FindReader(&p->Format,Stream->OffsetMin,Stream->OffsetMax);
  1302. if (Reader)
  1303. Stream->Stream.Reader = Reader;
  1304. }
  1305. }
  1306. ArrayClear(&Array);
  1307. for (i=0;i<MAXREADER;++i)
  1308. {
  1309. format_reader* v = &p->Format.Reader[i];
  1310. if (v->Input && v->OffsetMax>0)
  1311. {
  1312. v->Seek(v,v->OffsetMin,SEEK_SET);
  1313. FlushBuffers = 1;
  1314. if (Reader == v)
  1315. OldReaderPos = v->OffsetMin;
  1316. }
  1317. }
  1318. if (!FlushBuffers)
  1319. Input->Seek(Input,OldFilePos,SEEK_SET);
  1320. else
  1321. {
  1322. // probably first reader already allocated all the buffers
  1323. Reader->FilePos = -1;
  1324. Reader->Seek(Reader,OldReaderPos,SEEK_SET);
  1325. }
  1326. }
  1327. static int Set(avi* p,int No,const void* Data,int Size)
  1328. {
  1329. if (No == NODE_SETTINGSCHANGED)
  1330. UpdateAviFrameRate(p);
  1331. return FormatBaseSet(&p->Format,No,Data,Size);
  1332. }
  1333. static void FreeStream(avi* p, avistream* Stream)
  1334. {
  1335. free(Stream->Index);
  1336. free(Stream->SuperIndex);
  1337. ArrayClear(&Stream->ZeroChunk);
  1338. }
  1339. static int Create(avi* p)
  1340. {
  1341. p->Format.Format.Set = (nodeset)Set;
  1342. p->Format.Init = (fmtfunc)Init;
  1343. p->Format.Done = (fmtvoid)Done;
  1344. p->Format.Seek = (fmtseek)Seek;
  1345. p->Format.ReadPacket = (fmtreadpacket)ReadPacket;
  1346. p->Format.FreeStream = (fmtstream)FreeStream;
  1347. p->Format.MinHeaderLoad = MAX_INT; //manualy setting HeaderLoaded
  1348. return ERR_NONE;
  1349. }
  1350. static const nodedef AVI = 
  1351. {
  1352. sizeof(avi),
  1353. AVI_ID,
  1354. FORMATBASE_CLASS,
  1355. PRI_DEFAULT,
  1356. (nodecreate)Create,
  1357. };
  1358. void AVI_Init()
  1359. {
  1360. NodeRegisterClass(&AVI);
  1361. }
  1362. void AVI_Done()
  1363. {
  1364. NodeUnRegisterClass(AVI_ID);
  1365. }