AVI.c
上传用户:super_houu
上传日期:2008-09-21
资源大小:4099k
文件大小:131k
源码类别:

DVD

开发平台:

Others

  1. if (currEntry.dwFlags & AVI_IS_KEY_FRAME)
  2. {
  3. /* A key frame was found - saving it */
  4. if ((NO_STREAM == _mpeg4AudioStreamID) || (TRUE == _bAVIVideoBeforeAudio))
  5. {
  6. /* Save the key frame without audio info */
  7. if ( FALSE == _saveIdxEntry(ulCurrFrameNumber, currEntry.dwChunkOffset,
  8. currEntry.dwChunkLength, 0, 0, 0, 0) )
  9. {
  10. dbg_printf(("FATAL: _aquireAndProcessIdx() Failed [3]n"));
  11. AuxCache_GetFileTerminate();
  12. #if (defined(SUPPORT_FLASH_CARD) && (!defined(I86_HW_FCU)))
  13. if(!IS_PLAYING_CARD)
  14. #endif
  15. free(_idxEntries);
  16. _idxEntries = NULL;
  17. _bMPEG4TrickModeOn = FALSE;
  18. #ifdef USE_HEAP
  19. //    sc_Free(idxFIFO, ((FIFO_LEN*sizeof(IdxFIFOElement) + 4 -1)/4));
  20.         free(idxFIFO);
  21. #endif
  22. return FALSE;
  23. }
  24. }
  25. else
  26. {
  27. /* Save the key frame with the corresponding audio info  */
  28. if ( FALSE == _saveIdxEntry(ulCurrFrameNumber, currEntry.dwChunkOffset,
  29. currEntry.dwChunkLength, dwCurrAudioChunkOffset, 
  30. dwCurrAudioChunkDelta,
  31. (UINT16)(ulCurrFrameNumber-ulFramesBeforeAudioCh),
  32. 0) )
  33. {
  34. dbg_printf(("FATAL: _aquireAndProcessIdx() Failed [3]n"));
  35. AuxCache_GetFileTerminate();
  36. #if (defined(SUPPORT_FLASH_CARD) && (!defined(I86_HW_FCU)))
  37. if(!IS_PLAYING_CARD)
  38. #endif
  39. free(_idxEntries);
  40. _idxEntries = NULL;
  41. _bMPEG4TrickModeOn = FALSE;
  42. #ifdef USE_HEAP
  43. //    sc_Free(idxFIFO, ((FIFO_LEN*sizeof(IdxFIFOElement) + 4 -1)/4));
  44.         free(idxFIFO);
  45. #endif
  46. return FALSE;
  47. }
  48. }
  49. }
  50. /* Updating the audio info */
  51. if ((NO_STREAM != _mpeg4AudioStreamID) && (FALSE == bIsFirstAudioChunk)  && (FALSE == _bAVIVideoBeforeAudio)) 
  52. {
  53. if ( (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE) /*&&
  54.  (TRUE == _aviFileInfo.bIsNandub)*/ )
  55. {
  56. /* VBR audio stream */
  57. /* Calculate the audio verses the video time and check 
  58.  * whether we should skip to the next audio chunks.
  59.  */
  60. // <<< Robin_2004_0519_A, change the index processing when VBR audio
  61. while (ulCurrVideoTime > ulCurrAudioTime)
  62. {
  63. ulCurrAudioTime += dwAudioSkip;
  64. if (!iAudioReminderCounter100)
  65. {
  66. ulCurrAudioTime += dwAudioSkipRemider100;
  67. iAudioReminderCounter100 =100;
  68. iAudioReminderCounter10000--;
  69. if (!iAudioReminderCounter10000)
  70. {
  71. ulCurrAudioTime += dwAudioSkipRemider10000;
  72. iAudioReminderCounter10000 =100;
  73. }
  74. }
  75. iAudioReminderCounter100--;
  76. // >>> Robin_2004_0519_A
  77. if (fifoHead != fifoTail)
  78. {
  79. /* Remove from the head of FIFO */
  80. #if 0//def USE_HEAP
  81. {
  82. IdxFIFOElement fifoEntry;
  83.                         sc_GetBytes(idxFIFO, fifoHead*(sizeof(IdxFIFOElement)), sizeof(IdxFIFOElement), (BYTE*)(&fifoEntry));
  84. dwCurrAudioChunkOffset = fifoEntry.dwAudioChunksOffsets;
  85. dwCurrAudioChunkSize = fifoEntry.dwAudioChunksLengths;
  86. ulFramesBeforeAudioCh = fifoEntry.dwAudioChunksFrames;
  87.                         fifoHead++;
  88. }
  89. #else
  90. dwCurrAudioChunkOffset = idxFIFO[fifoHead].dwAudioChunksOffsets;
  91. dwCurrAudioChunkSize = idxFIFO[fifoHead].dwAudioChunksLengths;
  92. ulFramesBeforeAudioCh = idxFIFO[fifoHead++].dwAudioChunksFrames;
  93. #endif
  94. fifoHead &= FIFO_WRAPAOURND;
  95. dwTotalAudioLength --;
  96. }
  97. else
  98. {
  99. /* FIFO underflow */
  100. // Robin_1119_2004_B, there is not left audio data
  101. if (dwTotalAudioLength != 0)
  102. {
  103. _bAVIVideoBeforeAudio = TRUE;
  104. tr_printf(("WARNING: The VBR audio chunk fifo underlow!n"));
  105. }
  106. break;
  107. }
  108. }
  109. // <<< Robin_2004_0519_A, change the index processing when VBR audio
  110. ulCurrVideoTime += dwVideoSkip;
  111. if (!iVideoReminderCounter100)
  112. {
  113. ulCurrVideoTime += dwVideoSkipRemider100;
  114. iVideoReminderCounter100 =100;
  115. iVideoReminderCounter10000--;
  116. if (!iVideoReminderCounter10000)
  117. {
  118. ulCurrVideoTime += dwVideoSkipRemider10000;
  119. iVideoReminderCounter10000 =100;
  120. }
  121. }
  122. iVideoReminderCounter100--;
  123. // >>> Robin_2004_0519_A
  124. }
  125. else
  126. {
  127. /* CBR audio stream */
  128. dwCurrAudioChunkDelta += dwAudioSkip;
  129.                
  130. if (!iAudioReminderCounter100)
  131. {
  132. dwCurrAudioChunkDelta += dwAudioSkipRemider100;
  133. iAudioReminderCounter100 = 100;
  134. iAudioReminderCounter10000--;
  135. if (!iAudioReminderCounter10000)
  136. {
  137. dwCurrAudioChunkDelta += dwAudioSkipRemider10000;
  138. iAudioReminderCounter10000 = 100;
  139. }
  140. }
  141. iAudioReminderCounter100--;
  142. /* Update the audio corresponding to the next video frame */
  143. /* Check whether we are still in the same audio chunk */
  144. while (dwCurrAudioChunkDelta > dwCurrAudioChunkSize)
  145. {
  146. /* Crossed to a different Audio chunk */
  147. // DWORD ulAudioChunkOffset, ulAudioChunkLength;
  148. if (fifoHead != fifoTail)
  149. {
  150. /* Remove from the head of FIFO */
  151. dwCurrAudioChunkDelta = dwCurrAudioChunkDelta - dwCurrAudioChunkSize;
  152. #if 0//def USE_HEAP
  153. {
  154. IdxFIFOElement fifoEntry;
  155.                         sc_GetBytes(idxFIFO, fifoHead*(sizeof(IdxFIFOElement)), sizeof(IdxFIFOElement), (BYTE *)(&fifoEntry));
  156. dwCurrAudioChunkOffset = fifoEntry.dwAudioChunksOffsets;
  157. dwCurrAudioChunkSize = fifoEntry.dwAudioChunksLengths;
  158. ulFramesBeforeAudioCh = fifoEntry.dwAudioChunksFrames;
  159.                         fifoHead++;
  160. }
  161. #else
  162. dwCurrAudioChunkOffset = idxFIFO[fifoHead].dwAudioChunksOffsets;
  163. dwCurrAudioChunkSize = idxFIFO[fifoHead].dwAudioChunksLengths;
  164. ulFramesBeforeAudioCh = idxFIFO[fifoHead++].dwAudioChunksFrames;
  165. #endif
  166. fifoHead &= FIFO_WRAPAOURND;
  167. dwTotalAudioLength -= dwCurrAudioChunkSize;
  168. }
  169. else
  170. {
  171. /* FIFO underflow */
  172. // Robin_1003_2004_D
  173. // Robin_1119_2004_B, there is not left audio data
  174. if (dwTotalAudioLength != 0)
  175. {
  176. _bAVIVideoBeforeAudio = TRUE;
  177. tr_printf(("WARNING: The CBR audio chunk fifo underlow!n"));
  178. }
  179. break;
  180. }
  181. }
  182. }
  183. }
  184. ulCurrFrameNumber++;
  185. }
  186. }
  187.         else if (( 'w' == currEntry.ucChunkID[2] )  && (FALSE == _bAVIVideoBeforeAudio))
  188. {
  189. /* Audio Entry */
  190. if (TRUE == bIsFirstAudioChunk)
  191. {
  192. dwCurrAudioChunkDelta = 0;
  193. dwCurrAudioChunkSize = currEntry.dwChunkLength;
  194. dwCurrAudioChunkOffset = currEntry.dwChunkOffset;
  195. ulFramesBeforeAudioCh = 0UL;
  196. bIsFirstAudioChunk = FALSE;
  197. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  198. dwTotalAudioLength --;
  199. else
  200. dwTotalAudioLength -= dwCurrAudioChunkSize;
  201. }
  202. else
  203. {
  204. if (((fifoTail+1)&FIFO_WRAPAOURND) != fifoHead)
  205. {
  206. //Insert to the tail of FIFO
  207. #if 0//def USE_HEAP
  208. {
  209. IdxFIFOElement fifoEntry;
  210. fifoEntry.dwAudioChunksOffsets = currEntry.dwChunkOffset;
  211. fifoEntry.dwAudioChunksLengths= currEntry.dwChunkLength;
  212. fifoEntry.dwAudioChunksFrames= ulCurrFrameNumber;
  213.                sc_SetBytes(idxFIFO, fifoTail*(sizeof(IdxFIFOElement)), sizeof(IdxFIFOElement), (BYTE*)(&fifoEntry));
  214.                fifoTail++;
  215. }
  216. #else
  217. idxFIFO[fifoTail].dwAudioChunksOffsets = currEntry.dwChunkOffset;
  218. idxFIFO[fifoTail].dwAudioChunksLengths= currEntry.dwChunkLength;
  219. idxFIFO[fifoTail++].dwAudioChunksFrames= ulCurrFrameNumber;
  220. #endif
  221. fifoTail &= FIFO_WRAPAOURND;
  222. }
  223. else
  224. {
  225. //FIFO overflow.
  226. tr_printf(("WARNING: IDX processing is cut during to low resourcesn"));
  227. // <<< Robin_0907_2004_B
  228. bIdxFifoOverFlow = TRUE;
  229. _bAVIVideoBeforeAudio = TRUE;
  230. // break;
  231. }
  232. }
  233. }
  234. // Robin_0117_2005, support AVI internal text subtitle
  235. #if 0
  236. else if ( 't' == currEntry.ucChunkID[2] )
  237. {
  238. // "Text "
  239. UINT16 uiSubtitleNum;
  240. for (uiSubtitleNum=0;uiSubtitleNum<_mpeg4SubtitleAvailableNum;uiSubtitleNum++)
  241. {
  242. sc_GetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  243.        (uiSubtitleNum * SIZE_OF_SUBTITLE_STREAM_INFO),
  244.        SIZE_OF_SUBTITLE_STREAM_INFO,
  245.        (BYTE*)&_mpeg4SubtitleStreamInfo
  246.       );
  247. if (uiStreamNumber == _mpeg4SubtitleStreamID && AVI_INTERNAL_TEXT == _mpeg4SubtitleType)
  248. {
  249. _mpeg4SubtitleOffsetInAvi = currEntry.dwChunkOffset;
  250. sc_SetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  251.        (uiSubtitleNum * SIZE_OF_SUBTITLE_STREAM_INFO),
  252.        SIZE_OF_SUBTITLE_STREAM_INFO,
  253.        (BYTE*)&_mpeg4SubtitleStreamInfo
  254.       );
  255. }
  256. }
  257. }
  258. #endif
  259. }
  260. AuxCache_GetFileTerminate();
  261. // <<< Robin_1003_2004_D
  262. // Robin_1222_2004, count the actual audio length
  263. if ((ulLeftSize == 0) && (ulCurrFrameNumber == _mpeg4VideoLength)) // index is completely scan
  264. {
  265. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  266. dwTotalAudioLength = _mpeg4AudioLength;
  267. else
  268. dwTotalAudioLength = _mpeg4AudioLength * _mpeg4AudioScale;
  269. if (dwTotalAudioCount != dwTotalAudioLength)
  270. {
  271. dbg_printf(("The original audio length is %ldn", _mpeg4AudioLength));
  272. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  273. _mpeg4AudioLength = dwTotalAudioCount;
  274. else
  275. _mpeg4AudioLength = dwTotalAudioCount/_mpeg4AudioScale;
  276. dbg_printf(("The actual audio length is %ldn", _mpeg4AudioLength));
  277. sc_SetBytes(SC_MPEG4_AUDIO_STREAM_INFO_ADDR,
  278.       (_mpeg4AudioCurrentDispIdx * SIZE_OF_AUDIO_STREAM_INFO),
  279.       SIZE_OF_AUDIO_STREAM_INFO,
  280.       (BYTE*)&_mpeg4AudioStreamInfo
  281.    );
  282. }
  283. }
  284. if ((TRUE == bIdxFifoOverFlow) || (TRUE == _bAVIVideoBeforeAudio))
  285. {
  286. UINT32 ulIndex = 0UL;
  287. IndexEntry indexEntry;
  288. DWORD dwAudioCount = 0UL;
  289. DWORD dwAudioLastCount = 0UL;
  290. DWORD dwAudioBoundary;
  291. UINT32 ulAudioChunkNumber = 0;
  292. UINT32 ulAudioChunkNumberBefore = 0;
  293. //  DWORD dwAudioChunkSize = 0UL;
  294. // DWORD dwPrevAudiochunkSize = 0UL;
  295. bFirstEntry = TRUE;
  296. ulCurrFrameNumber = 0UL;
  297. _uiAVICurrCachedIdxEntry = NUM_OF_IDX_ENTRIES_CACHE;
  298. wai_sem(SEM_DRAM_ID);
  299. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (ulIndex*sizeof(IndexEntry))),
  300.     (UINT16*)&indexEntry, sizeof(IndexEntry)/2);
  301. sig_sem(SEM_DRAM_ID);
  302. dwAudioBoundary = indexEntry.ulVideoFrameNumber * dwAudioSkip;
  303. dwAudioBoundary += ((indexEntry.ulVideoFrameNumber * dwAudioSkipRemider100)/100UL); 
  304. dwAudioBoundary += ((indexEntry.ulVideoFrameNumber * dwAudioSkipRemider10000)/10000UL); 
  305. while (ulLeftSizeStore > 0UL)
  306. {
  307. DWORD dwSizeOfCurrEntry;
  308. UINT8 uiStreamNumber;
  309. if (FALSE == _getIdxEntry(dwIdxClipStartAddr, dwIdxOffsetStore, ulLeftSizeSave, 
  310.   &currEntry, bFirstEntry, ulLeftSizeStore))
  311. {
  312. dbg_printf(("FATAL: _aquireAndProcessIdx() Failed [2]n"));
  313. if (ulLeftSizeStore < 4096UL) // can't get last two sectors
  314. break;
  315. AuxCache_GetFileTerminate();
  316. #if (defined(SUPPORT_FLASH_CARD) && (!defined(I86_HW_FCU)))
  317. if (!IS_PLAYING_CARD)
  318. #endif
  319. free(_idxEntries);
  320. _idxEntries = NULL;
  321. _bMPEG4TrickModeOn = FALSE;
  322. #ifdef USE_HEAP
  323. //    sc_Free(idxFIFO, ((FIFO_LEN*sizeof(IdxFIFOElement) + 4 -1)/4));
  324.         free(idxFIFO);
  325. #endif
  326. return FALSE;
  327. }
  328. bFirstEntry = FALSE;
  329. dwSizeOfCurrEntry = (DWORD)sizeof(currEntry);
  330. ulLeftSizeStore -= (UINT32)dwSizeOfCurrEntry;
  331. dwIdxOffsetStore += dwSizeOfCurrEntry;
  332. if (0 == currEntry.dwChunkOffset) // index corrupted
  333. continue;
  334. /* Calculating the stream number of the entry */
  335. uiStreamNumber = (currEntry.ucChunkID[0] - '0')*10 + currEntry.ucChunkID[1] - '0';
  336. /* Check whether the current entry does not belong to the current played AV streams */
  337. if ( (('d' == currEntry.ucChunkID[2]) && (uiStreamNumber != uiVideoStreamNum)) ||
  338.  (('w' == currEntry.ucChunkID[2]) && (uiStreamNumber != uiAudioStreamNum)) )
  339. {
  340. /* Not the current played stream - ignore it */
  341. continue;
  342. }
  343. if ( ('d' == currEntry.ucChunkID[2]) && (('c' == currEntry.ucChunkID[3]) || ('b' == currEntry.ucChunkID[3])) )
  344. {
  345. if (ulCurrFrameNumber <= indexEntry.ulVideoFrameNumber)
  346. {
  347. ulAudioChunkNumberBefore = ulAudioChunkNumber;
  348. }
  349. // RB_2005_0511, framenumber start from 0
  350. ulCurrFrameNumber++;
  351. }
  352. else if ( 'w' == currEntry.ucChunkID[2] )
  353. {
  354. if ( (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE))
  355. {
  356. dwAudioCount += dwAudioSkip;
  357. if (!iAudioReminderCounter100)
  358. {
  359. dwAudioCount += dwAudioSkipRemider100;
  360. iAudioReminderCounter100 =100;
  361. iAudioReminderCounter10000--;
  362. if (!iAudioReminderCounter10000)
  363. {
  364. dwAudioCount += dwAudioSkipRemider10000;
  365. iAudioReminderCounter10000 =100;
  366. }
  367. }
  368. iAudioReminderCounter100--;
  369. }
  370. else
  371. {
  372. dwAudioLastCount = dwAudioCount;
  373. dwAudioCount += currEntry.dwChunkLength;
  374. }
  375. while (dwAudioCount > dwAudioBoundary)
  376. {
  377. indexEntry.ulAudioChunkOffset = currEntry.dwChunkOffset;
  378. if ( (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE))
  379. {
  380. indexEntry.ulAudioChunkDelta = 0UL;
  381. }
  382. else
  383. {
  384. indexEntry.ulAudioChunkDelta = (dwAudioBoundary - dwAudioLastCount);
  385. }
  386.                         if (indexEntry.ulVideoFrameNumber >= ulCurrFrameNumber)
  387. {
  388. indexEntry.uiSkipVideoChunks = (UINT16)(indexEntry.ulVideoFrameNumber-ulCurrFrameNumber);
  389. indexEntry.uiSkipAudioChunks = 0;
  390. }
  391.                         else
  392.                         { 
  393.                             indexEntry.uiSkipVideoChunks = 0;
  394.                             indexEntry.uiSkipAudioChunks = (UINT16)(ulAudioChunkNumber - ulAudioChunkNumberBefore);
  395.                         }   
  396. // <<< Robin_1003_2004_C
  397. // check the audio/video is interleave 
  398. if (ABS_DIFF(indexEntry.ulAudioChunkOffset, indexEntry.ulVideoChunkOffset) > 0x1000000UL) // more than 16MB, not accuracy
  399. {
  400. bVideoAudioInterleave = FALSE;
  401. tr_printf(("WARNING: Video/Audio is not interleaved, playback without audio!n"));
  402.                         }
  403. // >>> Robin_1003_2004_C
  404. wai_sem(SEM_DRAM_ID);
  405. I49_WriteDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (ulIndex*sizeof(IndexEntry))),
  406.   (UINT16*)&indexEntry, sizeof(IndexEntry)/2);
  407. sig_sem(SEM_DRAM_ID);
  408. ulIndex ++;
  409. if (ulIndex >= _uiMPEG4NextIndexEntry )
  410. break;
  411. wai_sem(SEM_DRAM_ID);
  412. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (ulIndex*sizeof(IndexEntry))),
  413.   (UINT16*)&indexEntry, sizeof(IndexEntry)/2);
  414. sig_sem(SEM_DRAM_ID);
  415. if ( (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE))
  416. {
  417. /* VBR audio stream */
  418. dwAudioBoundary = indexEntry.ulVideoFrameNumber * dwVideoSkip;
  419. dwAudioBoundary += ((indexEntry.ulVideoFrameNumber * dwVideoSkipRemider100 + (
  420. (indexEntry.ulVideoFrameNumber * dwVideoSkipRemider10000)/100UL) )/100UL); 
  421. }
  422. else
  423. {
  424. /* CBR audio stream */
  425. dwAudioBoundary = indexEntry.ulVideoFrameNumber * dwAudioSkip;
  426. dwAudioBoundary += ((indexEntry.ulVideoFrameNumber * dwAudioSkipRemider100 +
  427. ((indexEntry.ulVideoFrameNumber * dwAudioSkipRemider10000)/100UL))/100UL); 
  428. }
  429. }
  430. ulAudioChunkNumber ++;
  431. }
  432. if (ulIndex >= _uiMPEG4NextIndexEntry )
  433. break;
  434. // Robin_1003_2004_C
  435. if (FALSE == bVideoAudioInterleave)
  436. break;
  437. }
  438. // >>> Robin_0907_2004_B
  439. }
  440. // >>> Robin_1003_2004_D
  441. AuxCache_GetFileTerminate();
  442. #if (defined(SUPPORT_FLASH_CARD) && (!defined(I86_HW_FCU)))
  443. if(!IS_PLAYING_CARD)
  444. #endif
  445. free(_idxEntries);
  446. _idxEntries = NULL;
  447. _dwMPEG4ProcessingEndAddr = (CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR, (((DWORD)(_uiMPEG4NextIndexEntry-1))*sizeof(IndexEntry))) >>9) <<9; // Robin_1119_2004_B, avoid the overflow
  448. _dwMPEG4ProcessingEndAddr = (_dwMPEG4ProcessingEndAddr>>9)<<9;
  449. #ifdef USE_AUX_SUBTITLES 
  450. _mpeg4ExternalSubtitleAddr = _dwMPEG4ProcessingEndAddr;
  451. #endif
  452. _bMPEG4IsIndexProcessed = TRUE;
  453. // <<< Robin_0907_2004_B
  454. if (_uiMPEG4NextIndexEntry > 1)
  455. _bMPEG4TrickModeOn = TRUE;
  456. else
  457. _bMPEG4TrickModeOn = FALSE;
  458. // >>> Robin_0907_2004_B
  459. dbg_printf(("_aquireAndProcessIdx FINISHED, total time: %ld msecn", gen_timer()/1000UL-ulStartTime));
  460. dbg_printf(("Total saved I frames: %dn", _uiMPEG4NextIndexEntry));
  461. dbg_printf(("Start address of index table: 0x%lxn",_dwMPEG4ProcessingEndAddr));
  462. #ifdef USE_HEAP
  463. //    sc_Free(idxFIFO, ((FIFO_LEN*sizeof(IdxFIFOElement) + 4 -1)/4));
  464.         free(idxFIFO);
  465. #endif
  466. return TRUE;
  467. }
  468. ///////////////////////////////////////////////////////////////////////////
  469. // Function name : _aviProcessTimeToAddressInfo
  470. // Purpose : Calculate the frame number corresponding to the given
  471. //   time and the index entry used for it.
  472. // Input Parameters : dwClipStartAddr  - The start address of the AVI file.
  473. //   WORD    - The requested time (msec)
  474. // Return type : TRUE if the operation succeeded, FALSE otherwise.
  475. // Description : The function seeks for the closest frame number in 
  476. //   the idx table.
  477. ///////////////////////////////////////////////////////////////////////////
  478. static BOOL _aviProcessTimeToAddressInfo(DWORD dwClipStartAddr, WORD wTime)
  479. {
  480. UINT32 ulFirstIFrame;
  481. UINT32 ulSecondIFrame;
  482. WORD   wFirstITime;
  483. WORD   wSecondITime;
  484. UINT32 ulFirstIIdx;
  485. UINT32 ulSecondIIdx;
  486. UINT16 uiFirstDelta;
  487. UINT16 uiSecondDelta;
  488. UINT32 ulRequestedFrameNum;
  489. dbg_printf(("_aviProcessTimeToAddressInfo()n"));
  490. if (FALSE == _getAdjacentIFrames(dwClipStartAddr, wTime,
  491.                &ulFirstIFrame, &ulSecondIFrame,
  492.  &wFirstITime, &wSecondITime,
  493.              &ulFirstIIdx, &ulSecondIIdx) )
  494. {
  495. dbg_printf(("WARNING: _aviProcessTimeToAddressInfo() FAILEDn"));
  496. return FALSE;
  497. }
  498. /* Calculate the frame number corresponding to the given time */
  499. ulRequestedFrameNum = caclFrameOfTime(wTime,
  500.  _mpeg4VideoRate,
  501.  _mpeg4VideoScale);
  502. /* Check the closest I frame */
  503. uiFirstDelta = (ulFirstIFrame >= ulRequestedFrameNum) ? 
  504.    (UINT16)(ulFirstIFrame - ulRequestedFrameNum) :
  505.    (UINT16)(ulRequestedFrameNum - ulFirstIFrame);
  506. uiSecondDelta = (ulSecondIFrame >= ulRequestedFrameNum) ?
  507.     (UINT16)(ulSecondIFrame - ulRequestedFrameNum) :
  508.     (UINT16)(ulRequestedFrameNum - ulSecondIFrame);
  509.    if (PM_GetRepeatAB())
  510.         _ulMPEG4RequestedFrameIndex =  ulFirstIIdx;
  511.     else
  512.      _ulMPEG4RequestedFrameIndex = (uiFirstDelta <= uiSecondDelta) ? ulFirstIIdx : ulSecondIIdx;
  513. dbg_printf(("Actual frame number %ld, calculated frame number %ldn", ulRequestedFrameNum,
  514.             (_ulMPEG4RequestedFrameIndex == ulFirstIIdx) ? ulFirstIFrame : ulSecondIFrame));
  515. return TRUE;
  516. }
  517. ////////////////////////////////////////////////////////////////////////////
  518. // Function name : _aviScan
  519. // Purpose : Handle scanning of the avi file.
  520. // Input Parameters : iIndexIncrement - The increment to reach the next
  521. // index entry that needs to be played.
  522. //   bContinue - indicates whether the scanning has just
  523. //   started or not.
  524. // Return type : TRUE if the operation succeeded, FALSE otherwise.
  525. // Description : The function accesses the next entry in the idx table
  526. //   and asks the decoder and the drive to play that entry.
  527. ////////////////////////////////////////////////////////////////////////////
  528. static BOOL _aviScan(INT8 iIndexIncrement, BOOL bContinue)
  529. {
  530. DWORD dwStartLBA;
  531. WORD wClipStartOffset;
  532. WORD wClipEndOffset;
  533. ULONG ulBlocksCnt;
  534. IndexEntry indexEntry;
  535. dbg_printf(("_aviScan()n"));
  536. #ifdef AVI_FF_NO_INDEX
  537. if (FALSE == _bMPEG4TrickModeOn)
  538. {
  539. if (TRUE == bContinue)
  540. {
  541. DEC_AVI_SetIOnly(FALSE);
  542. DEC_AVI_SetIPOnly(FALSE);
  543. DEC_AVI_EnableFinishCB(FALSE);
  544. ie_send(IE_CORE_CDNAV_FINISHED);
  545. return TRUE;
  546. }
  547. DEC_AVI_GetVideoStatus((UINT32*)&_uiMPEG4StartTime, (UINT32*)&ulBlocksCnt);
  548. dwStartLBA = _dwMPEG4ClipStartLBA + (_ulMPEG4TotalBlocksCnt - ulBlocksCnt);
  549. wClipStartOffset = 0;
  550. wClipEndOffset = _wMPEG4ClipEndOffset;
  551. }
  552. else
  553. #endif
  554. {
  555. /* If we are not yet in scan mode, calculate the entry in the index corresponding to the current time */
  556. if (FALSE == bContinue)
  557. {
  558.   if (FALSE == _aviProcessTimeToAddressInfo(_dwMPEG4FileLocation, _uiMPEG4StartTime))
  559. {
  560. dbg_printf(("WARNNING: _aviScan() Failed [1]n"));
  561. return FALSE;
  562. }
  563. }
  564. /* Check whether we scanned the whole idx table */
  565. if ( (((INT32)_ulMPEG4RequestedFrameIndex + (INT32)iIndexIncrement) >= _uiMPEG4NextIndexEntry) || 
  566.  (((INT32)_ulMPEG4RequestedFrameIndex + (INT32)iIndexIncrement) < 0) )
  567. {
  568. DEC_AVI_EnableFinishCB(FALSE);
  569. ie_send(IE_CORE_CDNAV_FINISHED);
  570. return TRUE;
  571. }
  572. /* Calculate the next entry to be played */
  573. _ulMPEG4RequestedFrameIndex = (UINT32)((INT32)_ulMPEG4RequestedFrameIndex + (INT32)iIndexIncrement);
  574. wai_sem(SEM_DRAM_ID);
  575. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,(_ulMPEG4RequestedFrameIndex*sizeof(IndexEntry))),
  576.    (UINT16*)&indexEntry, sizeof(IndexEntry)/2);
  577. sig_sem(SEM_DRAM_ID);
  578. /* Calculate the playback addresses */
  579. dwStartLBA = _dwMPEG4ClipStartLBA +
  580.          ( (_wMPEG4ClipStartOffset + indexEntry.ulVideoChunkOffset - FOURCC_FIELD_LENGTH) >> 11);
  581. wClipStartOffset = (WORD)((_wMPEG4ClipStartOffset + indexEntry.ulVideoChunkOffset
  582. - FOURCC_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE);
  583. ulBlocksCnt = (wClipStartOffset + indexEntry.ulVideoChunkSize +
  584.     FOURCC_FIELD_LENGTH + SIZE_FIELD_LENGTH + LOGICAL_BLOCK_SIZE - 1) / LOGICAL_BLOCK_SIZE;
  585. #ifdef SUPPORT_FLASH_CARD
  586. if(IS_PLAYING_CARD)
  587. ulBlocksCnt += 16;
  588. #endif
  589. wClipEndOffset = (WORD)((wClipStartOffset + indexEntry.ulVideoChunkSize +
  590.   FOURCC_FIELD_LENGTH + SIZE_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE);
  591. wClipEndOffset += (wClipEndOffset % 2); /* Word alignment */
  592.     if (0 == wClipEndOffset)
  593.     {
  594.        wClipEndOffset = 2048;
  595.     }
  596. /* Calculate the start time */
  597. _uiMPEG4StartTime = caclTimeOfFrame(indexEntry.ulVideoFrameNumber,
  598.   _mpeg4VideoRate,
  599.   _mpeg4VideoScale);
  600. }
  601. if (FALSE == bContinue)
  602. {
  603. /* Scanning just started, re initialize the decoder */
  604. DWORD dwSampleRate;
  605. UINT8 uiAudioSID;
  606. UINT8 uiAudioSIDDecoder;
  607. determineAudioInfo(&uiAudioSID, &uiAudioSIDDecoder, &dwSampleRate);
  608. prePlayProcessing(dwSampleRate, NO_STREAM, NO_STREAM, 0xFF, FALSE);
  609. API_ADPSetMp3_Throw_Out_Cntr(0);
  610. /* Signal to the DVP the decision */
  611. DEC_AVI_SetIOnly(TRUE);
  612. DEC_AVI_SetIPOnly(FALSE);
  613. DEC_AVI_ResetDemuxStatus();
  614. DEC_AVI_SetStartVideoChunks(indexEntry.ulVideoFrameNumber);
  615. /* The order of the calls to the functions should not be changed! */
  616. DEC_AVI_SetPlaybackParams(wClipStartOffset, wClipEndOffset, _uiMPEG4StartTime, 0, 0);
  617. PE_Clips_SetPlaybackRange(dwStartLBA, ulBlocksCnt, UNLIMITED_FILE_SIZE);
  618. if (!PE_Clips_Playback_Sectors(DRVCF_CDSPEED_1X | DRVF_PLAY_CD_AV_DATA, dwStartLBA, ulBlocksCnt))
  619. {
  620. dbg_printf(("FATAL: _aviScan() Failed [3]n"));
  621. return FALSE;
  622. }
  623. }
  624. else
  625. {
  626. /* Stopping the current drive playback */
  627. drv_abort_play();
  628. /* Signal to the DVP the decision */
  629. DEC_AVI_SetIOnly(TRUE);
  630. DEC_AVI_SetIPOnly(FALSE);
  631. DEC_AVI_ResetDemuxStatus();
  632. DEC_AVI_SetStartVideoChunks(indexEntry.ulVideoFrameNumber);
  633. /* Set the next playback request to the decoder and to the drive */
  634. DEC_AVI_SetPlaybackParams(wClipStartOffset, wClipEndOffset, _uiMPEG4StartTime, 0, 0);
  635. PE_Clips_SetPlaybackRange(dwStartLBA, ulBlocksCnt, UNLIMITED_FILE_SIZE);
  636. if (!PE_Clips_Playback_Sectors(DRVCF_CDSPEED_1X | DRVF_PLAY_CD_AV_DATA, dwStartLBA, ulBlocksCnt))
  637. {
  638. dbg_printf(("WARNNING: _aviScan() Failed [4]n"));
  639. return FALSE;
  640. }
  641. }
  642. /* Install call back from the decoder */
  643. DEC_AVI_EnableFinishCB(TRUE);
  644. return TRUE;
  645. }
  646. // Robin_1011_2004_D
  647. #ifdef PATCH_VIDEO_NOT_B
  648. ///////////////////////////////////////////////////////////////////////////
  649. // Function name : _detectBVOP
  650. // Purpose : Detect if B-VOP exist
  651. // Input Parameters : 
  652. // Return type : if B-VOP exist, return TRUE. if not exist, return FALSE
  653. // Description :
  654. ///////////////////////////////////////////////////////////////////////////
  655. static BOOL _aviDetectBVOP()
  656. {
  657. DWORD dwStartLBA,dwClipStartOffset;
  658. DWORD pdwOffset;
  659. BYTE videoStreamID1[FOURCC_FIELD_LENGTH], videoStreamID2[FOURCC_FIELD_LENGTH];
  660. IndexEntry* pIndexEntry;
  661. BYTE videoHeaderBuff[64]; // 64 is enough
  662. WORD wVideoHeaderSize;
  663. FOURCCInfo pFourccInfo;
  664. BYTE videoObjectType;
  665. int i,j;
  666. if (_mpeg4VideoCodec== DIVX_3_11 ||
  667. _mpeg4VideoCodec == DIVX_4_12 ||
  668. _mpeg4VideoCodec == MP43 ||
  669. _mpeg4VideoCodec == DIVX_UNKNOWN)
  670. {
  671. dbg_printf(("Video isn't B encoded.n"));
  672. return FALSE;
  673. }
  674. wVideoHeaderSize = 64;
  675. if (_mpeg4VideoHeaderDataLength > 0)
  676. {
  677. wVideoHeaderSize = min(wVideoHeaderSize,MPEG4_VIDEO_HEADER_CACHE_SIZE);
  678. wai_sem(SEM_DRAM_ID);
  679. I49_ReadDRAMData(SC_MPEG4_VIDEO_HEADER_DATA_ADDR, &videoHeaderBuff, wVideoHeaderSize);
  680. sig_sem(SEM_DRAM_ID);
  681. }
  682. else
  683. {
  684. dwStartLBA = _dwMPEG4ClipStartLBA;;
  685. dwClipStartOffset = (DWORD)_wMPEG4ClipStartOffset;;
  686. if (TRUE == _bMPEG4TrickModeOn)
  687. {
  688. pIndexEntry = malloc(sizeof(IndexEntry));
  689. if( NULL == pIndexEntry)
  690. {
  691. dbg_printf(("FATAL: _aviDetectBVOP() Failed [4]: Malloc failed. Low system resource.n"));
  692. return FALSE;
  693. }
  694. wai_sem(SEM_DRAM_ID);
  695. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,0),
  696.  (UINT16*)pIndexEntry, sizeof(IndexEntry)/2);
  697. sig_sem( SEM_DRAM_ID );
  698. pdwOffset = dwClipStartOffset + pIndexEntry->ulVideoChunkOffset + FOURCC_FIELD_LENGTH;
  699. free(pIndexEntry);
  700. }
  701. else
  702. {
  703. videoStreamID1[0] = '0';
  704. videoStreamID1[1] = _mpeg4VideoStreamID + '0';
  705. videoStreamID1[2] = 'd';
  706. videoStreamID1[3] = 'c';
  707. videoStreamID2[0] = '0';
  708. videoStreamID2[1] = _mpeg4VideoStreamID + '0';
  709. videoStreamID2[2] = 'd';
  710. videoStreamID2[3] = 'b';
  711. pdwOffset = dwClipStartOffset;
  712. while(TRUE)
  713. {
  714. /* Get the next FOURCC */
  715. if (FALSE == _getNextFOURCC(dwStartLBA, pdwOffset, &pFourccInfo))
  716. {
  717. dbg_printf(("_detectBVOP(): _searchForFOURCC() Failedn"));
  718. return FALSE;
  719. }
  720. //there is "LISTxxxxrec " before the chunk header
  721.                 if (TRUE == pFourccInfo.bIsList && 
  722.                     0 == strnicmp((LPSTR)pFourccInfo.aFOURCCBuff, "rec ", FOURCC_FIELD_LENGTH))
  723.                 {
  724. pdwOffset += FOURCC_FIELD_LENGTH;
  725. pdwOffset += SIZE_FIELD_LENGTH;
  726.                     pdwOffset += FOURCC_FIELD_LENGTH;
  727.                     if (FALSE == _getNextFOURCC(dwStartLBA, pdwOffset, &pFourccInfo))
  728.                     {
  729.                         dbg_printf(("_detectBVOP(): _searchForFOURCC() Failedn"));
  730.                         return FALSE;
  731.                     }                    
  732.                 }
  733. /* Check whether this is the FOURCC we are looking for */
  734. if (0 == strnicmp((LPSTR)pFourccInfo.aFOURCCBuff, (LPSTR)videoStreamID1, FOURCC_FIELD_LENGTH) ||
  735. 0 == strnicmp((LPSTR)pFourccInfo.aFOURCCBuff, (LPSTR)videoStreamID2, FOURCC_FIELD_LENGTH))
  736. {
  737. /* Reach the chunk/list data area */
  738. pdwOffset += FOURCC_FIELD_LENGTH;
  739. pdwOffset += SIZE_FIELD_LENGTH;
  740. break;
  741. }
  742. /* Skip to the next list/chunk */
  743. pdwOffset += FOURCC_FIELD_LENGTH;
  744. pdwOffset += SIZE_FIELD_LENGTH;
  745. pdwOffset += (DWORD)pFourccInfo.ulSize;
  746. }
  747. }
  748. if (!AuxCache_GetBytes(dwStartLBA, pdwOffset, wVideoHeaderSize, videoHeaderBuff))
  749. {
  750. dbg_printf(("_detectBVOP(): AuxCache_GetBytes Failedn"));
  751. return FALSE;
  752. }
  753. }
  754. for (i=0; i<(wVideoHeaderSize -4);i++)
  755. {
  756. if(videoHeaderBuff[i] != 0)
  757. continue;
  758. if(videoHeaderBuff[i+1] != 0)
  759. continue;
  760. if(videoHeaderBuff[i+2] == 1)
  761. {
  762. if ((videoHeaderBuff[i+3] >= 20) && (videoHeaderBuff[i+3] <= 0x2F)) // video obejct layer start code
  763. {
  764. break;
  765. }
  766. }
  767. }
  768. if (i >= (wVideoHeaderSize -4))
  769. return FALSE;
  770. i += 4;
  771. j=0;
  772. j+=1;// random_accessible_vol
  773. videoObjectType = (videoHeaderBuff[i+(j+1)/8]<<1) + (videoHeaderBuff[i+1+(j+1)/8]>>7);
  774. dbg_printf(("Video object 0x%xn",videoObjectType));
  775. j+=8;//video_object_type_indication
  776. if (((videoHeaderBuff[i+(j+1)/8] >> (7-(j%8))) & 0x1) == 0x1)
  777. j+=7;
  778. j+=1;
  779. if (((videoHeaderBuff[i+(j+1)/8] >> (7-4 -(j%8))) & 0xF) == 0xF) // 
  780. j+=16;
  781. j+=4;
  782. if (((videoHeaderBuff[i+(j+1)/8] >> (7-(j%8))) & 0x1) == 0x1)
  783. {
  784. j+=1;
  785. j+=2;
  786. if (((videoHeaderBuff[i+(j+1)/8] >> (7-(j%8))) & 0x1) == 0x1) // low delay
  787. {
  788. dbg_printf(("Video isn't B encoded.n"));
  789. return FALSE;
  790. }
  791. else
  792. return TRUE;
  793. }
  794. else
  795. {
  796. if(videoObjectType == 0x01) // simple 
  797. return FALSE;
  798. else if (videoObjectType == 0x11) // advanced simple
  799. return TRUE;
  800. else
  801. return FALSE;
  802. }
  803. }
  804. #endif
  805. /////////////////////////////////////////////////////////////////////////////
  806. // Public Services
  807. BOOL AVIClip_isKindOf(LPCWSTR i_pszFilename)
  808. {
  809. return GenericClip_isKindOf(i_pszFilename, CLIP_VALID_EXTENSIONS(AVI));
  810. }
  811. void AVIClip_construct(struct Clip_TAG *o_pThis, const FindData *i_pFileInfo)
  812. {
  813. GenericClip_construct(o_pThis, i_pFileInfo);
  814.    o_pThis->m_pConstAttr = &CLIP_CONST_ATTR(AVI);
  815. }
  816. ///////////////////////////////////////////////////////////////////////////
  817. // Function name : AVIClip_continueScanning
  818. // Purpose : Trigger the navigator to give the next playback 
  819. //   request during scanning.
  820. // Input Parameters : none
  821. // Return type : none
  822. // Description : The function acts as a callback from the DEMUX to 
  823. //   signal reaching the end of the previous playback
  824. //   request.
  825. ///////////////////////////////////////////////////////////////////////////
  826. void AVIClip_continueScanning(void)
  827. {
  828. /* Verify that we are in FF I only mode */
  829. #ifdef IP_SUPPORT
  830. if ( (gns.clips.iScanSpeed != 0) && (gns.clips.iScanSpeed != SCAN_SPEED_2X) )
  831. #else
  832. if (gns.clips.iScanSpeed != 0)
  833. #endif
  834. {
  835. _aviScan(_iMPEG4CurrentScanningMode, TRUE);
  836. }
  837. }
  838. /////////////////////////////////////////////////////////////////////////////
  839. // Virtual Methods
  840. #pragma argsused
  841. BOOL AVIClip_getExtendedInfo(const struct Clip_TAG *i_pThis, 
  842.  WORD i_pExtInfo_sc_handle)
  843. {
  844. // TBD - 'strn' chunk
  845. return FALSE;
  846. }
  847. #pragma argsused
  848. BOOL AVIClip_play(Clip *i_pThis, const ClipMarker *i_pResumeMarker, BOOL bCacheOnly) 
  849. DWORD dwClipStartAddr = (i_pThis->m_cfiInfo).dwFileLocation, dwStartLBA;
  850. WORD wClipStartOffset;
  851. WORD wClipEndOffset;
  852. FOURCCInfo movieList;
  853. DWORD dwMovieListOffset = AVI_HEADER_OFFSET;
  854. ULONG ulBlocksCnt;
  855. UINT8 uiAudioSID, uiAudioSIDDecoder;
  856. DWORD dwSamplingRate;
  857. UINT16 uiNumOfFramesToSkip = 0;
  858. // Robin_1003_2004_D
  859. UINT16 uiNumOfAudioChunksToSkip = 0;
  860. // Robin_1009_2004, large size of audio chunk, more than 2^16
  861. UINT32 uiNumOfAudBytesToSkip = 0;
  862. UINT32 uiNumOfFramesStart = 0;
  863. static DWORD dwFirstChunkOffset; // Robin_0809_2004, hold the value of fisrtchunkoffset when index not processing
  864. IndexEntry* pIndexEntry;
  865. // <<< Robin_0903_2004
  866. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE_MODE0
  867. static BYTE subFileSelect = 0;
  868. static UINT8 subtitleSelect = 0;
  869. #endif
  870. // >>> Robin_0903_2004
  871. static BYTE lastSubtitleStreamID;
  872. dbg_printf(("Playing AVI filen"));
  873. Logo_selectSource(eFrame);
  874. #if defined(NO_AUTO_PLAY_FOR_CLIPS) || defined(NO_AUTO_PLAY_ONLY_FOR_DVIX)
  875. if (g_patch_4_auto_play)
  876. {
  877. g_patch_4_auto_play = FALSE;
  878. return TRUE;
  879. }
  880. #endif
  881. _uiMPEG4TotalDVPIdleTime = 0;
  882. /* Check if the AVI info should be acquired */
  883. if (NULL == i_pResumeMarker)
  884. {
  885. _bMPEG4PauseToSlow = FALSE;
  886. _mpeg4SubtitleCurrentDispIdx = 0;
  887. _mpeg4AudioCurrentDispIdx = 0;
  888. _mpeg4ChapterCurrentDispIdx = 0;
  889. change_pallet = TRUE;
  890. _bMPEG4WasClockEnabled = FALSE;
  891. if (_uiMPEG4ProcessedFileAddr != dwClipStartAddr)        //Don't process index if already processed.
  892. _bMPEG4IsIndexProcessed = FALSE;
  893. _iMPEG4CurrentScanningMode = 0;
  894. _lAVIPreviousFrameNumber = -1;
  895. _uiMPEG4NumOfDecodedChunksMemory = 0;
  896. _bMPEG4TrickModeOn = TRUE;
  897. _uiMPEG4StartTime = 0;
  898. // _dwMPEG4ProcessingEndAddr = MPEG4_PROCESSING_BUFF_ADDR;
  899. // Clear shared RAM offsets that will be used 
  900. DEC_AVI_ClearSharedOffset(0); 
  901. DEC_AVI_ClearSharedOffset(1); 
  902. // RB_1124_2004, add "mpeg4 loading..." display 
  903. ie_send(IE_UI_MPEG4_LOADING_START);
  904. if (FALSE == _acquireAVIInfo(dwClipStartAddr)) 
  905. {
  906. Logo_selectSource(eStartup);
  907. Logo_display();
  908. //inform UI to display "Wrong File Content"
  909. ie_send(IE_UI_CLIPS_CLEAR_UI);
  910. core_report_error( IE_UI_REPORT_ERROR, (void *) CLIPSNAV_ERR_WRONGFILE_UOP );
  911. tr_printf(("FATAL: AVIClip_play() Failed [1]n"));
  912. usleep(300000UL);  // ensure UI accept the event
  913. return FALSE;
  914. }
  915. #ifdef  AVI_DRM_SUPPORT
  916. Logo_selectSource(eFrame);
  917. #endif
  918. if (_mpeg4AudioCurrentDispIdx >= _mpeg4AudioAvailableNum)
  919. {
  920. _mpeg4AudioCurrentDispIdx = 0;
  921. }
  922. if (_bAVIDrmOn)
  923. PS_Save();
  924. DEC_AVI_SetDrm( _bAVIDrmOn );
  925. if (DIVX_UNKNOWN == _mpeg4VideoCodec)
  926. {
  927. dbg_printf(("FATAL: AVIClip_play() Failed [2]n"));
  928. ie_send(IE_UI_CLIPS_CLEAR_UI);
  929. return FALSE;
  930. }
  931. // always first audio stream
  932. sc_GetBytes(SC_MPEG4_AUDIO_STREAM_INFO_ADDR,
  933. 0,
  934. SIZE_OF_AUDIO_STREAM_INFO,
  935. (BYTE*)&_mpeg4AudioStreamInfo
  936. );
  937. if (_mpeg4AudioAvailableNum == 0)
  938. _mpeg4AudioStreamID = NO_STREAM;
  939. ie_send(IE_UI_MPEG4_LOADING_START);
  940. #ifdef AVI_PROCCESS_IDX_ON_CLIP_START
  941. if (FALSE == _aquireAndProcessIdx(dwClipStartAddr, _mpeg4VideoStreamID, _mpeg4AudioStreamID, &dwFirstChunkOffset))
  942. {
  943. dbg_printf(("WARNING: Aquiring the INDEX FAILEDn"));
  944. }
  945. #endif // AVI_PROCCESS_IDX_ON_CLIP_START
  946. // <<< Robin_1003_2004_C
  947. if (FALSE == bVideoAudioInterleave)
  948. {
  949. _mpeg4AudioStreamID = NO_STREAM;
  950. }
  951. determineAudioInfo(&uiAudioSID, &uiAudioSIDDecoder, &dwSamplingRate);
  952. // >>> Robin_1003_2004_C
  953. #ifdef AVI_FF_NO_INDEX
  954. DEC_AVI_SetIndex(_bMPEG4TrickModeOn);
  955. #endif
  956. // Robin_0527_2004_A
  957. #ifdef USE_AUX_SUBTITLES 
  958. #ifdef USE_AUX_SUBTITLES 
  959. if (_bMPEG4IsIndexProcessed == FALSE) // mean no index
  960. _mpeg4ExternalSubtitleAddr = MPEG4_PROCESSING_BUFF_ADDR;
  961. #endif
  962. // <<< Robin_0903_2004
  963. // <<< Robin_0907_2004
  964. SI_CLIPS_SUB_CURRENT_DISP_IDX = SI_CLIPS_SUB_AVAILABLE_NUM;
  965. if (FALSE == initAuxSubtitles(&(i_pThis->m_cfiInfo), _mpeg4VideoScale, _mpeg4VideoRate))
  966. // >>> Robin_0907_2004
  967. {
  968. SI_CLIPS_SUB_CURRENT_DISP_IDX = 0;
  969. }
  970. // >>> Robin_0903_2004
  971. AuxCache_GetFileTerminate();
  972. #endif //USE_AUX_SUBTITLES 
  973. // <<< Robin_0903_2004
  974. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE_MODE0
  975. subFileSelect = Get_SubFile_Select();
  976. subtitleSelect = SI_CLIPS_SUB_CURRENT_DISP_IDX;
  977. #endif
  978. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  979. if (SI_CLIPS_SUB_AVAILABLE_NUM > 1)
  980. {
  981. sc_GetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  982. (SI_CLIPS_SUB_CURRENT_DISP_IDX * SIZE_OF_SUBTITLE_STREAM_INFO),
  983. SIZE_OF_SUBTITLE_STREAM_INFO,
  984. (BYTE*)&_mpeg4SubtitleStreamInfo
  985. );
  986. }
  987. #endif
  988. // >>> Robin_0903_2004
  989. /* Reaching the movie list FOURCC */
  990. if (FALSE == _searchForFOURCC(dwClipStartAddr, &dwMovieListOffset, AVI_MOVIE_LIST_ID, &movieList, FALSE, 0))
  991. {
  992. dbg_printf(("FATAL: AVIClip_play() Failed [3]n"));
  993. ie_send(IE_UI_CLIPS_CLEAR_UI);
  994. return FALSE;
  995. }
  996. #if 0
  997. {
  998. // search "AVIX"
  999. DWORD dwAvi2OffsetSec;
  1000. FOURCCInfo Avi2FourccInfo;
  1001. dwAvi2OffsetSec = dwMovieListOffset;
  1002. if (TRUE == _searchForFOURCC(dwClipStartAddr, &dwAvi2OffsetSec, RIFF_ID, &Avi2FourccInfo, FALSE, 0))
  1003. {
  1004. if (dwAvi2OffsetSec <= (i_pThis->m_cfiInfo).cbFileSize)
  1005. {
  1006. dwAvi2OffsetSec -= (DWORD)Avi2FourccInfo.ulSize;
  1007. if (TRUE == AuxCache_GetBytes(dwClipStartAddr, dwAvi2OffsetSec, (WORD)FOURCC_FIELD_LENGTH, Avi2FourccInfo.aFOURCCBuff))
  1008. {
  1009. /* Verifying that the RIFF file is an AVIX one */
  1010. if (0 == strnicmp((LPSTR)(Avi2FourccInfo.aFOURCCBuff), AVI2_ID, FOURCC_FIELD_LENGTH)) 
  1011. {
  1012. dbg_printf(("AVI2 FOURCC detected...n"));
  1013. dwAvi2OffsetSec += FOURCC_FIELD_LENGTH;
  1014. if (TRUE == _searchForFOURCC(dwClipStartAddr, &dwAvi2OffsetSec, AVI_MOVIE_LIST_ID, &Avi2FourccInfo, FALSE, 0))
  1015. {
  1016. movieList.ulSize += (dwAvi2OffsetSec - dwMovieListOffset) ;
  1017. dwMovieListOffset = dwAvi2OffsetSec;
  1018. }
  1019. }
  1020. }
  1021. }
  1022. }
  1023. }
  1024. #endif
  1025. /* Updating the offset to the start of the movie list data */
  1026. dwMovieListOffset -= (DWORD)movieList.ulSize;
  1027. dwMovieListOffset += LIST_TYPE_FIELD_LENGTH; 
  1028. /* Calculate and save playback addresses */
  1029. dwStartLBA = dwClipStartAddr + (dwMovieListOffset >> 11);
  1030. wClipStartOffset = (WORD)(dwMovieListOffset % LOGICAL_BLOCK_SIZE);
  1031. // <<< Robin_1014_2004, merge the Orion change, the playbackrange size should be smaller than the actual file size,  
  1032. if ((i_pThis->m_cfiInfo).cbFileSize < (wClipStartOffset + movieList.ulSize - LIST_TYPE_FIELD_LENGTH))
  1033. {
  1034. ulBlocksCnt = ((wClipStartOffset + ((i_pThis->m_cfiInfo).cbFileSize - dwMovieListOffset + LIST_TYPE_FIELD_LENGTH)  + 
  1035. LOGICAL_BLOCK_SIZE - 1) / LOGICAL_BLOCK_SIZE);
  1036. wClipEndOffset = (WORD)((wClipStartOffset + ((i_pThis->m_cfiInfo).cbFileSize - dwMovieListOffset + LIST_TYPE_FIELD_LENGTH) - LIST_TYPE_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE);
  1037. }
  1038. else
  1039. {
  1040. ulBlocksCnt = ((wClipStartOffset + movieList.ulSize - LIST_TYPE_FIELD_LENGTH + 
  1041. LOGICAL_BLOCK_SIZE - 1) / LOGICAL_BLOCK_SIZE);
  1042. wClipEndOffset = (WORD)((wClipStartOffset + movieList.ulSize - LIST_TYPE_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE);
  1043. }
  1044. // >>> Robin_1004_2004,
  1045. wClipEndOffset += (wClipEndOffset % 2); /* Word alignment */
  1046. if (0 == wClipEndOffset)
  1047. {
  1048. wClipEndOffset = 2048;
  1049. }
  1050. /*
  1051. in some AVI files, the chunk offset of index is given as an offset from the start of the file.
  1052. */
  1053. if (dwFirstChunkOffset == dwMovieListOffset)
  1054. {
  1055.  // <<< Robin_1003_2004_A
  1056. if (TRUE == _checkAVIClipOffset(dwClipStartAddr,dwMovieListOffset))
  1057. {
  1058. _dwMPEG4ClipStartLBA = dwStartLBA;
  1059. _wMPEG4ClipStartOffset = wClipStartOffset;
  1060. }
  1061.  // >>> Robin_1003_2004_A
  1062. else
  1063. {
  1064.      _dwMPEG4ClipStartLBA = dwClipStartAddr;
  1065.        _wMPEG4ClipStartOffset = 4;
  1066. }    
  1067. }
  1068. else
  1069. {
  1070. _dwMPEG4ClipStartLBA = dwStartLBA;
  1071. _wMPEG4ClipStartOffset = wClipStartOffset;
  1072. }
  1073. _wMPEG4ClipEndOffset = wClipEndOffset;
  1074. _ulMPEG4TotalBlocksCnt = ulBlocksCnt;
  1075. _dwMPEG4FileLocation = dwClipStartAddr;
  1076. // <<< Robin_1003_2004_C
  1077. if (FALSE == bVideoAudioInterleave)
  1078. {
  1079. pIndexEntry = malloc(sizeof(IndexEntry));
  1080. if( NULL == pIndexEntry)
  1081. {
  1082. dbg_printf(("FATAL: AVIClip_play() Failed [4]: Malloc failed. Low system resource.n"));
  1083. return FALSE;
  1084. }
  1085. wai_sem(SEM_DRAM_ID);
  1086. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,0),
  1087.  (UINT16*)pIndexEntry, sizeof(IndexEntry)/2);
  1088. sig_sem( SEM_DRAM_ID );
  1089. dwStartLBA = _dwMPEG4ClipStartLBA + 
  1090. ( (_wMPEG4ClipStartOffset + pIndexEntry->ulVideoChunkOffset - FOURCC_FIELD_LENGTH) >> 11);
  1091. wClipStartOffset = (_wMPEG4ClipStartOffset + pIndexEntry->ulVideoChunkOffset -
  1092. FOURCC_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE;
  1093. ulBlocksCnt = _ulMPEG4TotalBlocksCnt - (dwStartLBA - _dwMPEG4ClipStartLBA);
  1094. wClipEndOffset = _wMPEG4ClipEndOffset;
  1095. free(pIndexEntry);
  1096. }
  1097. // >>> Robin_1003_2004_C
  1098. /* Set total clip time */
  1099. // Robin_1003_2004_B
  1100. // Robin_1009_2004, total time is max value of video/audio playback time
  1101. {
  1102. UINT16 uVideoTotalPlaybackTime, uAudioTotalPlaybackTime;
  1103. uVideoTotalPlaybackTime = caclTimeOfFrame( _mpeg4VideoLength,
  1104.   _mpeg4VideoRate,
  1105. _mpeg4VideoScale);
  1106. if (_mpeg4AudioStreamID== NO_STREAM)
  1107. uAudioTotalPlaybackTime = 0;
  1108. else
  1109. // <<< Robin_1012_2004, calculate the total time of CBR/VBR audio 
  1110. {
  1111. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  1112. {
  1113. // VBR audio
  1114. uAudioTotalPlaybackTime = caclTimeOfFrame(_mpeg4AudioLength,
  1115.    _mpeg4AudioRate,
  1116.    _mpeg4AudioScale);
  1117. }
  1118. else
  1119. {
  1120. // CBR audio
  1121. uAudioTotalPlaybackTime =  (_mpeg4AudioLength *
  1122. _mpeg4AudioScale) / 
  1123. _mpeg4AudioAvgBytesPerSec;
  1124. }    
  1125. }
  1126. // >>> Robin_1012_2004,
  1127. gns.clips.uTotalPlaybackTime = MAX(uVideoTotalPlaybackTime,uAudioTotalPlaybackTime);    
  1128.    
  1129. }
  1130. dbg_printf(("Total Clip Time: %d secn", gns.clips.uTotalPlaybackTime));
  1131. #ifdef PATCH_VIDEO_NOT_B
  1132. _bMPEG4IsBVopExist = _aviDetectBVOP();
  1133. #endif
  1134. // Robin_0117_2005, support AVI internal text subtitle
  1135. #if 0
  1136. if (_mpeg4SubtitleType == AVI_INTERNAL_TEXT && _mpeg4SubtitleStreamID != NO_STREAM)
  1137. {
  1138. aviParseInternalSubtileText();
  1139. lastSubtitleStreamID = _mpeg4SubtitleStreamID;
  1140. }
  1141. #endif
  1142. ie_send(IE_UI_CLIPS_CLEAR_UI);
  1143. }
  1144. else
  1145. {
  1146. #ifdef AVI_FF_NO_INDEX
  1147. if ((FALSE == _bMPEG4TrickModeOn) && (_uiMPEG4NextIndexEntry == 0))
  1148.       {
  1149. /* Resuming, handled as goto time */
  1150. DEC_AVI_ChangedSubtitle(_mpeg4SubtitleStreamID);
  1151. determineAudioInfo(&uiAudioSID, &uiAudioSIDDecoder, &dwSamplingRate);
  1152. DEC_AVI_GetVideoStatus((UINT32*)&_uiMPEG4StartTime, (UINT32*)&ulBlocksCnt);
  1153. dwStartLBA = _dwMPEG4ClipStartLBA + (_ulMPEG4TotalBlocksCnt - ulBlocksCnt);
  1154. wClipStartOffset = 0;
  1155. wClipEndOffset = _wMPEG4ClipEndOffset;
  1156. uiNumOfFramesToSkip = 0;
  1157. uiNumOfAudBytesToSkip = 0;
  1158. uiNumOfFramesStart = 0;
  1159. }
  1160. else
  1161. #endif
  1162. {
  1163. UINT16 uAudioTotalPlaybackTime;
  1164. /* Resuming, handled as goto time */
  1165. DEC_AVI_ChangedSubtitle(_mpeg4SubtitleStreamID);
  1166. /* Calculate the video frame to skip to */
  1167. _aviProcessTimeToAddressInfo(i_pResumeMarker->dwAddress, i_pResumeMarker->uTime);
  1168. // <<< Robin_1003_2004_C
  1169. if (FALSE == bVideoAudioInterleave)
  1170. {
  1171. _mpeg4AudioStreamID = NO_STREAM;
  1172. }
  1173. // >>> // Robin_1003_2004_C
  1174. determineAudioInfo(&uiAudioSID, &uiAudioSIDDecoder, &dwSamplingRate);
  1175. // <<< Robin_1210_2004, if the resume time exceed the total audio time, set audio is no stream 
  1176. {
  1177. if (_mpeg4AudioStreamID== NO_STREAM)
  1178. uAudioTotalPlaybackTime = 0;
  1179. else if (_mpeg4AudioLength == 0)
  1180. uAudioTotalPlaybackTime = gns.clips.uTotalPlaybackTime;
  1181. else
  1182. {
  1183. if (_mpeg4AudioScale == AVI_VBR_AUD_STREAM_SCALE)
  1184. {
  1185. // VBR audio
  1186. uAudioTotalPlaybackTime = caclTimeOfFrame(_mpeg4AudioLength,
  1187.      _mpeg4AudioRate,
  1188.      _mpeg4AudioScale);
  1189. }
  1190. else
  1191. {
  1192. // CBR audio
  1193. uAudioTotalPlaybackTime =  (_mpeg4AudioLength *
  1194. _mpeg4AudioScale) / 
  1195. _mpeg4AudioAvgBytesPerSec;
  1196. }    
  1197. }
  1198. }
  1199. // >>> Robin_1210_2004
  1200. pIndexEntry = malloc(sizeof(IndexEntry));
  1201. if( NULL == pIndexEntry)
  1202. {
  1203. dbg_printf(("FATAL: AVIClip_play() Failed [5]: Malloc failed. Low system resource.n"));
  1204. return FALSE;
  1205. }
  1206. wai_sem(SEM_DRAM_ID);
  1207. I49_ReadDRAMData(CALC_IDX_ENTRY_ADDRESS(MPEG4_PROCESSING_BUFF_ADDR,(_ulMPEG4RequestedFrameIndex*sizeof(IndexEntry))),
  1208.    (UINT16*)pIndexEntry, sizeof(IndexEntry)/2);
  1209. sig_sem( SEM_DRAM_ID );
  1210. dbg_printf(("Resuming: Frame number %ld, Video chunk offset 0x%lx, Audio chunk offset 0x%lxn",
  1211. pIndexEntry->ulVideoFrameNumber, pIndexEntry->ulVideoChunkOffset, 
  1212. pIndexEntry->ulAudioChunkOffset));
  1213. /* Calculate the actual start time */
  1214. _uiMPEG4StartTime = caclTimeOfFrame(pIndexEntry->ulVideoFrameNumber,
  1215.   _mpeg4VideoRate,
  1216.   _mpeg4VideoScale);
  1217. dbg_printf(("time %d secn", _uiMPEG4StartTime));
  1218. if (_uiMPEG4StartTime >= uAudioTotalPlaybackTime)
  1219. {
  1220. uiAudioSID = NO_STREAM;
  1221. uiAudioSIDDecoder = NoAudio;
  1222. }
  1223. if ((NO_STREAM == _mpeg4AudioStreamID) || /*(TRUE == _bAVIVideoBeforeAudio) ||*/
  1224. (_uiMPEG4StartTime >= uAudioTotalPlaybackTime)) //Robin_1210_2004
  1225. {
  1226. /* Start playback from the exact video chunk */
  1227. dwStartLBA = _dwMPEG4ClipStartLBA + 
  1228. ( (_wMPEG4ClipStartOffset + pIndexEntry->ulVideoChunkOffset - FOURCC_FIELD_LENGTH) >> 11);
  1229. wClipStartOffset = (WORD)((_wMPEG4ClipStartOffset + pIndexEntry->ulVideoChunkOffset -
  1230. FOURCC_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE);
  1231. uiNumOfFramesToSkip = 0;
  1232. uiNumOfAudBytesToSkip = 0;
  1233. uiNumOfFramesStart = pIndexEntry->ulVideoFrameNumber;
  1234. }
  1235. else
  1236. {
  1237. /* Start playback from the audio chunk preceeding the correcsponding video */
  1238. // <<< Robin_1003_2004_D
  1239. if (pIndexEntry->ulAudioChunkOffset < pIndexEntry->ulVideoChunkOffset)
  1240. {
  1241. dwStartLBA = _dwMPEG4ClipStartLBA + 
  1242. ( (_wMPEG4ClipStartOffset + pIndexEntry->ulAudioChunkOffset - FOURCC_FIELD_LENGTH) >> 11);
  1243. wClipStartOffset = (_wMPEG4ClipStartOffset + pIndexEntry->ulAudioChunkOffset -
  1244. FOURCC_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE;
  1245. }
  1246. else
  1247. {
  1248. dwStartLBA = _dwMPEG4ClipStartLBA + 
  1249. ( (_wMPEG4ClipStartOffset + pIndexEntry->ulVideoChunkOffset - FOURCC_FIELD_LENGTH) >> 11);
  1250. wClipStartOffset = (_wMPEG4ClipStartOffset + pIndexEntry->ulVideoChunkOffset -
  1251. FOURCC_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE;
  1252. }
  1253. uiNumOfFramesToSkip = pIndexEntry->uiSkipVideoChunks;
  1254. uiNumOfAudioChunksToSkip = pIndexEntry->uiSkipAudioChunks;
  1255. // Robin_1009_2004
  1256. uiNumOfAudBytesToSkip = pIndexEntry->ulAudioChunkDelta;
  1257. uiNumOfFramesStart = pIndexEntry->ulVideoFrameNumber;
  1258. }
  1259. free(pIndexEntry);
  1260. #ifdef AVI_AUDIO_CHANGE_ONSCAN    //PATCH: To keep audio frame alignment for audio change on fly, because index table is not accurate
  1261. if (_mpeg4AudioCurrentDispIdx != 0)       // Robin_0125_2005_B, only first audio stream be processed druing the index processing   
  1262. uiNumOfAudBytesToSkip = 0;
  1263. #endif
  1264. dbg_printf(("ADP skip %ld bytes, DVP skip %d frames, DVP start %ld framen",
  1265. uiNumOfAudBytesToSkip, uiNumOfFramesToSkip,uiNumOfFramesStart));
  1266. ulBlocksCnt = _ulMPEG4TotalBlocksCnt - (dwStartLBA - _dwMPEG4ClipStartLBA);
  1267. wClipEndOffset = _wMPEG4ClipEndOffset;
  1268. }
  1269. // <<< Robin_0903_2004
  1270. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE_MODE0
  1271. if (subFileSelect != Get_SubFile_Select())
  1272. {
  1273. MPEG4SubtitleStreamInfo mpeg4LastSubtitleStreamInfo;
  1274. while(SI_CLIPS_SUB_AVAILABLE_NUM > 0)
  1275. {
  1276. sc_GetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  1277. ((SI_CLIPS_SUB_AVAILABLE_NUM-1) * SIZE_OF_SUBTITLE_STREAM_INFO),
  1278. SIZE_OF_SUBTITLE_STREAM_INFO,
  1279. (BYTE*)&mpeg4LastSubtitleStreamInfo
  1280. );
  1281. if(mpeg4LastSubtitleStreamInfo.type > INTERNAL_SUBT)
  1282. SI_CLIPS_SUB_AVAILABLE_NUM--;
  1283. else
  1284. break;
  1285. }
  1286. // <<< Robin_0907_2004
  1287. SI_CLIPS_SUB_CURRENT_DISP_IDX = SI_CLIPS_SUB_AVAILABLE_NUM;
  1288. if (FALSE == initAuxSubtitles(&(i_pThis->m_cfiInfo), _mpeg4VideoScale, _mpeg4VideoRate))
  1289. {
  1290. SI_CLIPS_SUB_CURRENT_DISP_IDX = 0;
  1291. }
  1292. AuxCache_GetFileTerminate();
  1293. }
  1294. else if ((SI_CLIPS_SUB_CURRENT_DISP_IDX < SI_CLIPS_SUB_AVAILABLE_NUM) && (_mpeg4SubtitleType == SAMI)
  1295. && (subtitleSelect != SI_CLIPS_SUB_CURRENT_DISP_IDX))
  1296. {
  1297. UINT16 uiSubNum = SI_CLIPS_SUB_AVAILABLE_NUM;
  1298. MPEG4SubtitleStreamInfo mpeg4LastSubtitleStreamInfo;
  1299. while(uiSubNum > 0)
  1300. {
  1301. sc_GetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  1302. ((uiSubNum-1) * SIZE_OF_SUBTITLE_STREAM_INFO),
  1303. SIZE_OF_SUBTITLE_STREAM_INFO,
  1304. (BYTE*)&mpeg4LastSubtitleStreamInfo
  1305. );
  1306. if(mpeg4LastSubtitleStreamInfo.type > INTERNAL_SUBT)
  1307. uiSubNum--;
  1308. else
  1309. break;
  1310. }
  1311. if ((SI_CLIPS_SUB_AVAILABLE_NUM - uiSubNum) > 1 ) // sami with multi-language
  1312. {
  1313. SI_CLIPS_SUB_AVAILABLE_NUM = uiSubNum;
  1314. if (FALSE == initAuxSubtitles(&(i_pThis->m_cfiInfo), _mpeg4VideoScale, _mpeg4VideoRate))
  1315. {
  1316. SI_CLIPS_SUB_CURRENT_DISP_IDX = 0;
  1317. }
  1318. AuxCache_GetFileTerminate();
  1319. }
  1320. }
  1321. // >>> Robin_0907_2004
  1322. subFileSelect = Get_SubFile_Select();
  1323. subtitleSelect = SI_CLIPS_SUB_CURRENT_DISP_IDX;
  1324. if (SI_CLIPS_SUB_AVAILABLE_NUM > 1)
  1325. {
  1326. sc_GetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  1327. (SI_CLIPS_SUB_CURRENT_DISP_IDX * SIZE_OF_SUBTITLE_STREAM_INFO),
  1328. SIZE_OF_SUBTITLE_STREAM_INFO,
  1329. (BYTE*)&_mpeg4SubtitleStreamInfo
  1330. );
  1331. }
  1332. if (SI_CLIPS_SUB_CURRENT_DISP_IDX == MAX_SUB_PER_CLIP)
  1333. _mpeg4SubtitleStreamID = NO_STREAM;
  1334. #endif
  1335. // >>> Robin_0903_2004
  1336. // Robin_0117_2005, support AVI internal text subtitle
  1337. #if 0
  1338. if (_mpeg4SubtitleType == AVI_INTERNAL_TEXT && _mpeg4SubtitleStreamID != NO_STREAM 
  1339. && lastSubtitleStreamID != _mpeg4SubtitleStreamID)
  1340. {
  1341. aviParseInternalSubtileText();
  1342. lastSubtitleStreamID = _mpeg4SubtitleStreamID;
  1343. }
  1344. #endif
  1345. }
  1346. prePlayProcessing(dwSamplingRate, uiAudioSID, uiAudioSIDDecoder, (i_pThis->m_pConstAttr)->m_eVideoSID,
  1347.    (NULL != i_pResumeMarker) ? FALSE : TRUE);
  1348. #if 0  //FW0408_2005D Move to prePlayProcessing()
  1349. // Set AVI video scaling
  1350. DEC_EnableManualScaling(PROG_SCALER_MODE_CCRAM);
  1351. DEC_SetViewMode(gps->view_mode);
  1352. #endif
  1353. // JG_0819_2004: FF/FB->PLAY/PAUSE need not to do scaling again
  1354. //FW_0526_2005B Comment out, move to prePlayProcessing()
  1355. //if (NULL == i_pResumeMarker)
  1356. //gcst.mNeedScaling = TRUE;
  1357. // <<< Robin_1011_2004, skip bytes by DVP
  1358. // API_ADPSetMp3_Throw_Out_Cntr(uiNumOfAudBytesToSkip);
  1359. API_ADPSetMp3_Throw_Out_Cntr(0);
  1360. uiNumOfAudBytesToSkip = (uiNumOfAudBytesToSkip>>1)<<1; // word align
  1361. #ifdef  D_ENABLE_ADPCM_SUPPORT
  1362. if (_mpeg4AudioCodec == ADPCM || _mpeg4AudioCodec == PCM)
  1363. uiNumOfAudBytesToSkip = (uiNumOfAudBytesToSkip/_mpeg4AudioBlockAlign_ADPCM) * _mpeg4AudioBlockAlign_ADPCM;
  1364. #endif
  1365. #ifdef D_ENABLE_DIVX_WMA_SUPPORT
  1366. if (_mpeg4AudioCodec == WMA)
  1367. uiNumOfAudBytesToSkip = (uiNumOfAudBytesToSkip/_mpeg4AudioBlockAlign_WMA) * _mpeg4AudioBlockAlign_WMA;
  1368. #endif
  1369. DEC_MP4_SetFirstSkipBytes(0UL,uiNumOfAudBytesToSkip,0UL);
  1370. // Robin_0715_2004, merge changelist #24806
  1371. // API_ADP_UpdateTaskParam( UPDATE_TASK_PARAM_MP3_THROW_OUT_CNTR,0 , NOT_SEND_TO_ADP);
  1372. // >>> Robin_1011_2004
  1373. DEC_AVI_SetStartVideoChunks(uiNumOfFramesStart);
  1374. // Robin_1003_2004_D
  1375. DEC_AVI_SetPlaybackParams(wClipStartOffset, wClipEndOffset, _uiMPEG4StartTime, uiNumOfFramesToSkip,uiNumOfAudioChunksToSkip );
  1376. PE_Clips_SetPlaybackRange(dwStartLBA, ulBlocksCnt, UNLIMITED_FILE_SIZE);
  1377. if (IS_CD_MEDIA)
  1378. {
  1379. drv_set_bit_rate(DRV_HIGH_BITRATE_E);
  1380. }
  1381. if (!PE_Clips_Playback_Sectors(DRVCF_CDSPEED_1X | DRVF_PLAY_CD_AV_DATA, dwStartLBA, ulBlocksCnt))
  1382. {
  1383. dbg_printf(("FATAL: AVIClip_play() Failed [6]n"));
  1384. return FALSE;
  1385. }
  1386. return TRUE;
  1387. }
  1388. #pragma argsused
  1389. void AVIClip_pause(Clip *i_pThis, BOOL bEnable) 
  1390. dbg_printf(("AVIClip_pause(%d)n", bEnable));
  1391. if (bEnable) 
  1392. {
  1393. /* in case we were in FF, */
  1394. if (gns.clips.iScanSpeed != 0)
  1395. {
  1396. int watchdog = 100;
  1397. AVIClip_scan(i_pThis, 0); /* Resume playback */
  1398. //Wait until enter NSPB
  1399. while (DEC_getState() != DEC_LL_STATUS0_C_STATE_NSPB && --watchdog)
  1400. {
  1401. usleep(5000UL);
  1402. }
  1403. }
  1404. /* Clear DVP indication that this is a pause-stop (and not pause) */
  1405. DEC_AVI_ClearDemuxSharedBit(AVI_FILE_PAUSE_OFFSET, AVI_FILE_PAUSE_BIT);
  1406. API_ADPSetMp3_Throw_Out_Cntr(0);
  1407. /* Pause the Decoder */
  1408. DEC_PlaybackCommand(DEC_PLAYBACK_CMD_PAUSE, NULL);
  1409. }
  1410. else 
  1411. {
  1412. #ifdef USE_AUX_SUBTITLES
  1413. if (FALSE != areAuxSubtitlePresent()) // Robin_0528_2004_A, disable AuxSubtitle function if it not availabe
  1414. {
  1415. // perform seek in subtitles storage
  1416. // replace 0 with the correct time, once it can be determined before playback
  1417. // actually resumes
  1418. subtitleGoToTime(0);
  1419. setSubtitlesPlayMode(TRUE);
  1420. }
  1421. #endif //USE_AUX_SUBTITLES 
  1422. /* Resume the Decoder */
  1423. /* in case we were in FF, terminate it and resume playback */
  1424. DEC_PlaybackCommand(DEC_PLAYBACK_CMD_RESUME, NULL);
  1425. }
  1426. }
  1427. #pragma argsused
  1428. void AVIClip_refresh(Clip *i_pThis) 
  1429. {
  1430. #ifdef MPP_SUPPORT
  1431. /* just enable MPP after playback, otherwise screen green or flash */
  1432. if( (PST_STOP != gcs.pstate) && (gns.clips.iCurrentTime >= 1) )
  1433. {
  1434. DEC_SetMPP( gcst.mMPP_Enable );
  1435. }
  1436. #endif
  1437. }
  1438. #pragma argsused
  1439. enClipStatus AVIClip_getStatus(const Clip *i_pThis)
  1440. {
  1441. UINT32 uiNumOfDecodedChunksCurrent;
  1442. UINT16 uiVideoDecodingError;
  1443. /* If we are in FF/FB I only, don't regard this status */
  1444. #ifdef IP_SUPPORT
  1445. if ( (PST_SCAN == gcs.pstate) && (SCAN_SPEED_2X != gns.clips.iScanSpeed) )
  1446. #else
  1447. if (PST_SCAN == gcs.pstate)
  1448. #endif
  1449. {
  1450. return eCS_Busy;
  1451. }
  1452. /* In NSPB check the DVP video status and perform error handling if it gets stuck */
  1453. DEC_AVI_GetVideoDecodingStatus(&uiNumOfDecodedChunksCurrent,&uiVideoDecodingError);
  1454. #ifdef SUPPORT_FLASH_CARD
  1455. if(IS_PLAYING_CARD)
  1456. _uiMPEG4TotalDVPIdleTime += 50; /* Core tick - 200 msec , slow down the counter for card*/
  1457. else
  1458. #endif
  1459. _uiMPEG4TotalDVPIdleTime += 200; /* Core tick - 200 msec */
  1460. if (PST_PLAY == gcs.pstate && 
  1461.  0 != _uiMPEG4NumOfDecodedChunksMemory &&
  1462.  _uiMPEG4NumOfDecodedChunksMemory == uiNumOfDecodedChunksCurrent &&
  1463.  (_uiMPEG4TotalDVPIdleTime >= DVP_VIDEO_TASK_WATCHDOG_TIME || uiVideoDecodingError == 0xF) &&
  1464.  _uiMPEG4NumOfDecodedChunksMemory != _mpeg4VideoLength )
  1465. {
  1466. ClipMarker mClipMarker;
  1467. UINT32 ulNextIIdx;
  1468. WORD wNextITime;
  1469. tr_printf(("DVP video error...n"));
  1470. /* Resume playback from the next I frame */
  1471. _uiMPEG4NumOfDecodedChunksMemory = 0; /* Prevent re-initiating */
  1472. _uiMPEG4TotalDVPIdleTime = 0;
  1473. if (TRUE == _getNextIFrames((i_pThis->m_cfiInfo).dwFileLocation, uiNumOfDecodedChunksCurrent,
  1474.                   &ulNextIIdx, &wNextITime) )
  1475. {
  1476. if(ulNextIIdx == _uiMPEG4NextIndexEntry)
  1477. {
  1478. DEC_AVI_EnableFinishCB(FALSE);
  1479. ie_send(IE_CORE_CDNAV_FINISHED);
  1480. }
  1481. mClipMarker.dwAddress = (i_pThis->m_cfiInfo).dwFileLocation;
  1482. if(wNextITime <= mClipMarker.uTime)
  1483. mClipMarker.uTime = wNextITime+1;
  1484. else
  1485. mClipMarker.uTime = wNextITime;
  1486. (i_pThis->m_pConstAttr->m_vtable.m_pfPlay)(i_pThis, &mClipMarker, FALSE);
  1487. }
  1488. else
  1489. {
  1490. ie_send(IE_CORE_CDNAV_FINISHED);
  1491. return eCS_Busy;
  1492. }
  1493. }
  1494. else if ( (_uiMPEG4NumOfDecodedChunksMemory != uiNumOfDecodedChunksCurrent) || (0 == _uiMPEG4NumOfDecodedChunksMemory) )
  1495. {
  1496. _uiMPEG4TotalDVPIdleTime = 0;
  1497. }
  1498. _uiMPEG4NumOfDecodedChunksMemory = uiNumOfDecodedChunksCurrent;
  1499. /* Normal speed playback */
  1500. if (drv_is_play_done() && DEC_IsPlaybackFinished(FALSE))
  1501. {
  1502. return eCS_Finished;
  1503. }
  1504. return eCS_Busy;
  1505. }
  1506. #pragma argsused
  1507. UINT16 AVIClip_getTime(const Clip *i_pThis) 
  1508. {
  1509. UINT16 uiStatus2 = inport(I64_STATUS_2);
  1510. /* Check if the DVP is not running yet */
  1511. if ( (uiStatus2 & DVP_UPDATED_SCLK_MASK) == 0 )
  1512. {
  1513. /* SCLK start time is still not updated by the DVP */
  1514. _bMPEG4WasClockEnabled = FALSE;
  1515. return _uiMPEG4StartTime;
  1516. }
  1517. else if (FALSE == _bMPEG4WasClockEnabled)
  1518. {
  1519. PE_Clips_EnableClock(TRUE, TRUE, _uiMPEG4StartTime);
  1520. _bMPEG4WasClockEnabled = TRUE;
  1521. }
  1522. #ifdef USE_AUX_SUBTITLES
  1523. if (FALSE != areAuxSubtitlePresent())// Robin_0528_2004_A
  1524.    {
  1525. // read the SCLK to get better update resolution than 1 sec.
  1526. checkAndHandleAuxSubtitles(PE_Clips_GetClock_Raw()); // Robin_2004_0517_B, resolution in ms
  1527. }
  1528. #endif // USE_AUX_SUBTITLES
  1529. _uiMPEG4StartTime = PE_Clips_GetClock();
  1530. return _uiMPEG4StartTime;
  1531. }
  1532. #pragma argsused
  1533. void AVIClip_abort(Clip *i_pThis, BOOL bMaintainStandby)
  1534. {
  1535. #ifdef MPP_SUPPORT
  1536. DEC_SetMPP(FALSE);
  1537. #endif
  1538. #ifdef AVI_DRM_SUPPORT
  1539.    if (NULL != pMasterKeyInstance)
  1540.    {
  1541.       free (pMasterKeyInstance);
  1542.       dbg_printf(("key instance memory free.n"));
  1543.       pMasterKeyInstance = NULL;
  1544.    }
  1545. #endif //AVI_DRM_SUPPORT
  1546.    
  1547. DEC_AVI_EnableFinishCB(FALSE);
  1548. if (IS_CD_MEDIA)
  1549. {
  1550. drv_set_bit_rate(DRV_NORMAL_BITRATE_E);
  1551. }
  1552. GenericClip_abort(i_pThis, bMaintainStandby);
  1553. }
  1554. #pragma argsused
  1555. void AVIClip_scan(Clip *i_pThis, int iScanSpeed)
  1556. {
  1557. INT8 iIndexIncrement;
  1558. // Robin_0903_2004_B, merge changlist #26190 from the Main DB
  1559. UINT8 eNoBScanSpeedMap = 0;
  1560. #ifdef A_SD340E
  1561. ///////wesleyj for divx scan speed
  1562. if(iScanSpeed > 0)
  1563. {
  1564. if(iScanSpeed >=30)
  1565. iScanSpeed = 8;
  1566. else if(iScanSpeed >=8)
  1567. iScanSpeed = 4;
  1568. else
  1569. iScanSpeed = 2;
  1570. }
  1571. else if(iScanSpeed < 0)
  1572. {
  1573. if(iScanSpeed < -30)
  1574. iScanSpeed = -20;
  1575. else if(iScanSpeed < -8)
  1576. iScanSpeed = -8;
  1577. else if(iScanSpeed < -4)
  1578. iScanSpeed = -4;
  1579. else
  1580. iScanSpeed = -2;
  1581. }
  1582. ///////////////////////////////////
  1583. #endif
  1584. #ifdef AVI_FF_NO_INDEX
  1585. if (_bMPEG4TrickModeOn)
  1586. #endif
  1587. {
  1588. // <<< Robin_0903_2004_B, merge changlist #26190 from the Main DB
  1589. if (iScanSpeed > 0)
  1590. {
  1591. if (iScanSpeed <=2)
  1592. eNoBScanSpeedMap = 4;
  1593. else if (iScanSpeed <=4)
  1594. eNoBScanSpeedMap = 8;
  1595. else
  1596. eNoBScanSpeedMap = 20;
  1597. }
  1598. else if(iScanSpeed < -8)
  1599. {
  1600. iScanSpeed = -20;
  1601. }
  1602. // >>> Robin_0903_2004_B
  1603. }
  1604. /* Check if we are in scanning */
  1605. if (iScanSpeed != 0)
  1606. {
  1607. if ( (PST_SLOW == gcs.pstate) || (PST_PLAY == gcs.pstate) || (PST_SCAN == gcs.pstate)  || (PST_PAUSE == gcs.pstate) )
  1608. {
  1609. #ifdef USE_AUX_SUBTITLES
  1610. if (FALSE != areAuxSubtitlePresent())// Robin_0528_2004_A
  1611. {
  1612. // stop subtitle seeking
  1613. setSubtitlesPlayMode(FALSE);
  1614. stopDisplayAuxSubtitles();
  1615. }
  1616. #endif //USE_AUX_SUBTITLES
  1617. #ifdef IP_SUPPORT
  1618. if ( ! FOUND_B_PICS_IN_CLIP && iScanSpeed > 0 )
  1619. {
  1620. // Robin_0903_2004_B
  1621. iScanSpeed = eNoBScanSpeedMap;
  1622. dbg_printf(("No B pictures detectedn"));
  1623. }
  1624.   if( _aviFileInfo.bDrmOn && iScanSpeed > 0 )
  1625. {
  1626. // Robin_0903_2004_B
  1627. iScanSpeed = eNoBScanSpeedMap;
  1628. dbg_printf(("DRM on, no FF-IPn"));
  1629. }
  1630. #else
  1631. if ( iScanSpeed > 0 )
  1632. {
  1633. #ifdef AVI_FF_NO_INDEX
  1634. if (_bMPEG4TrickModeOn)
  1635. #endif
  1636. // Robin_0903_2004_B
  1637.          iScanSpeed = eNoBScanSpeedMap;
  1638. }
  1639. #endif
  1640. dbg_printf(("AVIClip_scan(x%d)n", iScanSpeed));
  1641. /* Calculate the increment in the idx table */
  1642. switch (iScanSpeed)
  1643. {
  1644. case SCAN_SPEED_2X:
  1645. DEC_AVI_EnableFinishCB(FALSE);
  1646. DEC_AVI_SetIOnly(FALSE);
  1647. /* If we are moving from I to IP only, need to resume playback */
  1648. if (gns.clips.iScanSpeed != 0)
  1649. {
  1650. AVIClip_scan(i_pThis, 0); /* Resume playback */
  1651. AVIClip_scan(i_pThis, SCAN_SPEED_2X); /* Resume IP scanning mode */
  1652. return;
  1653. }
  1654. #ifdef AVI_FF_NO_INDEX
  1655. if (FALSE == _bMPEG4TrickModeOn)
  1656. DEC_AVI_EnableFinishCB(TRUE);
  1657. #endif
  1658. DEC_AVI_SetIPOnly(TRUE);
  1659. iIndexIncrement = I_P_INCREMENT;
  1660. _iMPEG4CurrentScanningMode = iIndexIncrement;
  1661. gns.clips.iScanSpeed = iScanSpeed;
  1662. gcs.pstate= PST_SCAN;
  1663. return;
  1664. case SCAN_SPEED_4X:
  1665. #ifdef AVI_FF_NO_INDEX
  1666. if (FALSE == _bMPEG4TrickModeOn)
  1667. {
  1668. DEC_AVI_SetIPOnly(FALSE);
  1669. DEC_AVI_SetIOnly(TRUE);
  1670. iIndexIncrement = ONE_I_INCREMENT;
  1671. _iMPEG4CurrentScanningMode = iIndexIncrement;
  1672. gns.clips.iScanSpeed = iScanSpeed;
  1673. gcs.pstate= PST_SCAN;
  1674. DEC_AVI_EnableFinishCB(TRUE);
  1675. return;
  1676. }
  1677. else
  1678. #endif
  1679. iIndexIncrement = ONE_I_INCREMENT;
  1680. break;
  1681. case SCAN_SPEED_8X:
  1682. iIndexIncrement = TOW_I_INCREMENT;
  1683. break;
  1684. case SCAN_SPEED_20X:
  1685. iIndexIncrement = FOUR_I_INCREMENT;
  1686. break;
  1687. case (-SCAN_SPEED_2X):
  1688. iIndexIncrement = -ONE_I_INCREMENT;
  1689. break;
  1690. case (-SCAN_SPEED_4X):
  1691. iIndexIncrement = -TOW_I_INCREMENT;
  1692. break;
  1693. case (-SCAN_SPEED_8X):
  1694. iIndexIncrement = -FOUR_I_INCREMENT;
  1695. break;
  1696. case (-SCAN_SPEED_20X):
  1697. iIndexIncrement = -EIGHT_I_INCREMENT;
  1698. break;
  1699. }
  1700. /* Check if we changed from IP to I only mode */
  1701. if ( (gns.clips.iScanSpeed == SCAN_SPEED_2X) || (gns.clips.iScanSpeed == 0) )
  1702. {
  1703. gcs.pstate = PST_SCAN;
  1704. /* Start I only scan mode */
  1705. if (FALSE == _aviScan(iIndexIncrement, FALSE))
  1706. {
  1707. dbg_printf(("WARNNING: AVIClip_scan() FAILEDn"));
  1708. }
  1709. }
  1710. /*
  1711.  * Else - the DEMUX status polling time was enabled before,
  1712.  *  and so, when the time is triggered the scanning will continue
  1713.  *  according to the updated scanning mode
  1714.  */
  1715. gns.clips.iScanSpeed = iScanSpeed;
  1716. _iMPEG4CurrentScanningMode = iIndexIncrement;
  1717. }
  1718. }
  1719. else
  1720. {
  1721. /* Playing after scanning - resume playback */
  1722. ClipMarker mClipMarker;
  1723. #ifdef USE_AUX_SUBTITLES
  1724. if (FALSE != areAuxSubtitlePresent())// Robin_0528_2004_A
  1725. {
  1726. // replace 0 with the correct time, once it can be determined before playback
  1727. // actually resumes
  1728. subtitleGoToTime(0);
  1729. setSubtitlesPlayMode(TRUE);
  1730. }
  1731. #endif //USE_AUX_SUBTITLES 
  1732. #ifdef AVI_FF_NO_INDEX
  1733. if (FALSE == _bMPEG4TrickModeOn)
  1734. {
  1735. DEC_AVI_SetIPOnly(FALSE);
  1736. DEC_AVI_SetIOnly(FALSE);
  1737. DEC_AVI_EnableFinishCB(FALSE);
  1738. }
  1739. else
  1740. #endif
  1741. {
  1742. if (_iMPEG4CurrentScanningMode == I_P_INCREMENT)
  1743. {
  1744. DEC_AVI_SetIPOnly(FALSE);
  1745. }
  1746. else /* I only mode */
  1747. {
  1748. DEC_AVI_SetIOnly(FALSE);
  1749. /* Remove DEMUX callback */
  1750. DEC_AVI_EnableFinishCB(FALSE);
  1751. }
  1752. }
  1753. /* Save the info used for resuming */
  1754. mClipMarker.dwAddress = (i_pThis->m_cfiInfo).dwFileLocation;
  1755. mClipMarker.uTime = _uiMPEG4StartTime;
  1756. gns.clips.iScanSpeed = 0;
  1757. // gcs.pstate = PST_PLAY;
  1758. /* Resume playback */
  1759. (i_pThis->m_pConstAttr->m_vtable.m_pfPlay)(i_pThis, &mClipMarker, FALSE);
  1760. }
  1761. #pragma argsused
  1762. void AVIClip_recordMarker(const Clip *i_pThis, ClipMarker *o_pMarker)
  1763. {
  1764. dbg_printf(("AVIClip_recordMarker()n"));
  1765. #ifdef AVI_FF_NO_INDEX
  1766. if ((FALSE == _bMPEG4TrickModeOn) && (_uiMPEG4NextIndexEntry == 0))
  1767. {
  1768. UINT32 ulTime, ulBlocksCnt ;
  1769. DEC_AVI_GetVideoStatus(&ulTime, &ulBlocksCnt);
  1770. o_pMarker->dwAddress = _dwMPEG4ClipStartLBA + (_ulMPEG4TotalBlocksCnt - ulBlocksCnt);
  1771. o_pMarker->uTime = (UINT16)ulTime;
  1772. o_pMarker->uClipNumer = gns.clips.uCurrentClipNumber;
  1773. }
  1774. else
  1775. #endif
  1776. {
  1777. /* Saving the info needed for playback resuming */
  1778. o_pMarker->dwAddress = (i_pThis->m_cfiInfo).dwFileLocation;
  1779. o_pMarker->uTime = (i_pThis->m_pConstAttr->m_vtable.m_pfGetTime)(i_pThis);
  1780. o_pMarker->uClipNumer = gns.clips.uCurrentClipNumber;
  1781. }
  1782. }
  1783. void AVIClip_performErrorHandling(const Clip *i_pThis)
  1784. {
  1785. dbg_printf(("AVIClip_performErrorHandling()n"));
  1786. /* The current error handling is only in scanning mode */
  1787. /* Check whether we are in FF I only or not */
  1788. #ifdef IP_SUPPORT
  1789. if ( (gcs.pstate == PST_SCAN) && (gns.clips.iScanSpeed != SCAN_SPEED_2X) )
  1790. #else
  1791. if (gcs.pstate == PST_SCAN)
  1792. #endif
  1793. {
  1794. /* Remove the callback from the demux */
  1795. DEC_AVI_EnableFinishCB(FALSE);
  1796. /* Start I only FF from the beginning */
  1797. _aviScan(_iMPEG4CurrentScanningMode, FALSE);
  1798. #ifdef SUPPORT_FLASH_CARD
  1799. if(IS_PLAYING_CARD)
  1800. _uiMPEG4StartTime += gns.clips.iScanSpeed;
  1801. #endif
  1802. }
  1803. else
  1804. {
  1805. /* NSPB recovery, resume playback from the next I frame */
  1806. ClipMarker mClipMarker;
  1807. UINT32 ulNextIIdx;
  1808. WORD wNextITime;
  1809. if(_uiMPEG4NumOfDecodedChunksMemory > 0)
  1810. {
  1811. if (TRUE == _getNextIFrames((i_pThis->m_cfiInfo).dwFileLocation, _uiMPEG4NumOfDecodedChunksMemory,
  1812.                   &ulNextIIdx, &wNextITime) )
  1813. {
  1814. if(ulNextIIdx == _uiMPEG4NextIndexEntry)
  1815. {
  1816. DEC_AVI_EnableFinishCB(FALSE);
  1817. ie_send(IE_CORE_CDNAV_FINISHED);
  1818. }
  1819. mClipMarker.dwAddress = (i_pThis->m_cfiInfo).dwFileLocation;
  1820. if(wNextITime <= mClipMarker.uTime)
  1821. mClipMarker.uTime = wNextITime+1;
  1822. else
  1823. mClipMarker.uTime = wNextITime;
  1824. (i_pThis->m_pConstAttr->m_vtable.m_pfPlay)(i_pThis, &mClipMarker, FALSE);
  1825. }
  1826. }
  1827. /* Else - we can't do anything */
  1828. }
  1829. }