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

DVD

开发平台:

Others

  1. /**************************************************************
  2.  *  AuxSubtitles.c
  3.  **************************************************************
  4.  *  Description:
  5.  *  ============
  6.  *  Handling of auxiliary subtitles files
  7.  **************************************************************
  8.  *
  9.  *  Hagay Barel 10.11.03
  10.  **************************************************************/
  11. #include "Config.h" // Global Configuration - do not remove!
  12. #ifdef USE_AUX_SUBTITLES
  13. #ifdef _DEBUG
  14. #undef IFTRACE
  15. #ifdef DEBUG_AUX_SUBTITLES
  16. #define IFTRACE if (gTraceNavigator)
  17. #else
  18. #define IFTRACE
  19. #endif // DEBUG_AUX_SUBTITLES
  20. #include "Debugdbgmain.h"
  21. #endif // _DEBUG
  22. #include "PlaycoreNav_ClipsClip_Impl.h"
  23. #include "PlaycoreNav_ClipsGenericClip.h"
  24. #include "PlaycoreFileSysFileSystem.h"
  25. #include "PlaycoreExceptionException.h"
  26. #include "Decoderlow_levelDEC_LL_Reg.h"
  27. #include "KernelKer_API.H"
  28. #include "KernelEventDef.h"
  29. #include "PlaycoreScPadScPadAlloc.h"
  30. #include "PlaycoreScPadSCMGR.h"
  31. // <<< Robin_0903_2004
  32. //#include "PlaycoreNav_ClipsAVI_private.h"
  33. //#include "PlaycoreNav_ClipsAVI.h"
  34. #include "PlaycoreCoremainCoreGDef.h"
  35. // >>> Robin_0903_2004
  36. #ifdef DEBUG_AUX_SUBTITLES
  37. #include "CpuTimefunc.h"
  38. #endif
  39. #include "PlaycoreNav_ClipsAuxSubtitles.h"
  40. #include "PlaycoreNav_ClipsAuxSubtitlesCommonPrivate.h"
  41. #include "PlaycoreNav_ClipsMpeg4ClipsCommon.h"
  42. #ifdef SUPPORT_FLASH_CARD
  43. #include "drivefe_manager.h"
  44. #include "mediacardsincluderegister.h"
  45. #endif
  46. SubtitleStorageInterface* g_pSubtitleStorage = NULL;
  47. static BOOL _allocateStorageInterface(void);
  48. #ifdef AUX_SUBTITLES_INDEX
  49. SubtitleStorageIndex* g_pSubtitleIndex = NULL;
  50. static BOOL _allocateStorageIndex(void);
  51. #endif // AUX_SUBTITLES_INDEX
  52. #ifdef V882_FLASH_CARD
  53. BOOL _freeStorageInterfaceAndIndex(void);
  54. #else
  55. static BOOL _freeStorageInterfaceAndIndex(void);
  56. #endif//V882_FLASH_CARD
  57. static DWORD g_dwNextSubtitleUpdateSCLK = 0xffffffffL;
  58. static BYTE g_wSubtitleStatus = 0;
  59. DWORD g_dwSubtitleExtraOffset;
  60. #ifdef SUPPORT_FLASH_CARD
  61. BOOL bReadAuxSubtitle;
  62. #endif
  63. UINT16 getCurrentInstanceIndex(void);
  64. // Set when the reading pointer for subtitle storage points at the beginning of
  65. // a subtitle, cleared when it points to the end.
  66. #define AUX_SUBTITLE_START_DISPLAY_FLAG 1
  67. // Set when the string buffer was filled by the core task, but not yet handled
  68. // by the UI task
  69. #define AUX_SUBTITLE_BUFFER_LOCKED_FLAG 2
  70. // Set on normal playback - sequential subtitle seeking is performed.
  71. // Cleared on beginning of FF/FB/Goto
  72. #define AUX_SUBTITLE_PLAY_MODE_FLAG     4
  73. // Set when subtitles exist. When set, the UI will respond to the "Subtitle" key.
  74. #define AUX_SUBTITLE_AVAILABE_FLAG      8
  75. #define IS_AUX_SUBTITLE_START_DISPLAY  (g_wSubtitleStatus & AUX_SUBTITLE_START_DISPLAY_FLAG)
  76. #define IS_AUX_SUBTITLE_BUFFER_LOCKED  (g_wSubtitleStatus & AUX_SUBTITLE_BUFFER_LOCKED_FLAG)
  77. #define IS_AUX_SUBTITLE_PLAY_MODE     (g_wSubtitleStatus & AUX_SUBTITLE_PLAY_MODE_FLAG)
  78. // <<< Robin_0903_2004
  79. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  80. #define IS_AUX_SUBTITLE_EXIST     (g_wSubtitleStatus & AUX_SUBTITLE_AVAILABE_FLAG)
  81. #define IS_AUX_SUBTITLE_AVAILABE     ((g_wSubtitleStatus & AUX_SUBTITLE_AVAILABE_FLAG) && (_mpeg4SubtitleType> INTERNAL_SUBT))
  82. #else
  83. // <<< Robin_0907_2004
  84. #define IS_AUX_SUBTITLE_EXIST     (g_wSubtitleStatus & AUX_SUBTITLE_AVAILABE_FLAG)
  85. // >>> Robin_0907_2004
  86. #define IS_AUX_SUBTITLE_AVAILABE     (g_wSubtitleStatus & AUX_SUBTITLE_AVAILABE_FLAG)
  87. #endif
  88. // >>> Robin_0903_2004
  89. #define SET_AUX_SUBTITLE_START_DISPLAY(b) (g_wSubtitleStatus = (b) ? g_wSubtitleStatus | AUX_SUBTITLE_START_DISPLAY_FLAG : g_wSubtitleStatus & ~AUX_SUBTITLE_START_DISPLAY_FLAG )
  90. #define SET_AUX_SUBTITLE_BUFFER_LOCKED(b) (g_wSubtitleStatus = (b) ? g_wSubtitleStatus | AUX_SUBTITLE_BUFFER_LOCKED_FLAG : g_wSubtitleStatus & ~AUX_SUBTITLE_BUFFER_LOCKED_FLAG )
  91. #define SET_AUX_SUBTITLE_PLAY_MODE(b)     (g_wSubtitleStatus = (b) ? g_wSubtitleStatus | AUX_SUBTITLE_PLAY_MODE_FLAG     : g_wSubtitleStatus & ~AUX_SUBTITLE_PLAY_MODE_FLAG )
  92. #define SET_AUX_SUBTITLE_AVAILABE(b)      (g_wSubtitleStatus = (b) ? g_wSubtitleStatus | AUX_SUBTITLE_AVAILABE_FLAG      : g_wSubtitleStatus & ~AUX_SUBTITLE_AVAILABE_FLAG )
  93. // Robin_0527_2004_A
  94. #define CALC_SUBTITLE_ADDRESS(address, offset) (address - (offset >> 1) - STORAGE_INTERFACE_BUFFER_SIZE/2)
  95. // Robin_1003_2004_E
  96. /* Valid Extenions List */
  97. BEGIN_CLIP_VALID_EXTENSIONS_MAP(SUB)
  98. CLIP_VALID_EXTENSIONS_ENTRY(L"SUB")
  99. CLIP_VALID_EXTENSIONS_ENTRY(L"SRT")
  100. CLIP_VALID_EXTENSIONS_ENTRY(L"TXT")
  101. #ifdef SUPPORT_SAMI_SUBTITLE
  102. CLIP_VALID_EXTENSIONS_ENTRY(L"SMI")
  103. #endif
  104. CLIP_VALID_EXTENSIONS_ENTRY(L"SSA")
  105. CLIP_VALID_EXTENSIONS_ENTRY(L"ASS")
  106. CLIP_VALID_EXTENSIONS_ENTRY(L"PSB")
  107. #ifdef SUPPORT_SAMI_SUBTITLE
  108. CLIP_VALID_EXTENSIONS_ENTRY(L"SAMI")
  109. #endif
  110. END_CLIP_VALID_EXTENSIONS_MAP()
  111. /////////////////////////////////////////////////////////////////////////////////////////////
  112. // Function name : initAuxSubtitles
  113. // Purpose : Initializes auxiliary subtitles for a clip
  114. // Input Parameters : clipInfo   - Information about the clip for which
  115. // to initialize subtitles
  116. //   dwScale, dwRate - dwScale/dwRate is the number of seconds
  117. // per video frame
  118. // Return type : TRUE if subtitles were loaded, FALSE otherwise.
  119. // Description : The function looks for a subtitle files belonging to the given clip,
  120. //   performs parsing and initializes interrupt and event handlers.
  121. /////////////////////////////////////////////////////////////////////////////////////////////
  122. BOOL initAuxSubtitles(ClipFileInfo *clipInfo, DWORD dwScale, DWORD dwRate)
  123. {
  124. DWORD dwSubtitlesFileAddress;
  125. DWORD dwSubtitlesFileSize;
  126. SubtitleParsingFuncPtr pfParseSubtitles;
  127. WORD wSubtitleID; // Robin_0903_2004
  128.    /* SubtitlesFormatID sfFormatID; */
  129. #ifdef DEBUG_AUX_SUBTITLES
  130. UINT32 dwStart, dwEnd;
  131. #endif
  132. g_dwSubtitleExtraOffset = 0;
  133. // <<< Stivenz_1115_04: Memory optimization: Move g_SubtitleStorage and g_SubtitleIndex to heap.
  134. if(!_allocateStorageInterface())
  135. return FALSE;
  136. #ifdef AUX_SUBTITLES_INDEX
  137. if(!_allocateStorageIndex())
  138. {
  139. _freeStorageInterfaceAndIndex();
  140. return FALSE;
  141. }
  142. #endif
  143. // Stivenz_1115_04 >>>
  144.    // this flag determines whether the UI will respond to the "subtitle" key
  145.    // if subtitles exist, it would be set to true.
  146.    SET_AUX_SUBTITLE_AVAILABE(FALSE);
  147.    g_dwNextSubtitleUpdateSCLK = LAST_SUBTITLE_MARKER;
  148. #ifdef SUPPORT_FLASH_CARD
  149. if (IS_PLAYING_CARD)
  150. bReadAuxSubtitle = TRUE;
  151. #endif
  152. #ifdef DEBUG_AUX_SUBTITLES
  153.    dwStart=gen_timer();
  154. #endif
  155. // is there an associated subtitle file of a recognized format?
  156. // <<< Robin_0903_2004
  157. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  158. if (clipInfo->wSubFileCnt == 1)
  159. {
  160. wSubtitleID = 0;
  161. }
  162. else
  163. {
  164. wSubtitleID = Get_SubFile_Select();
  165. }
  166. if ( FALSE == findAndCheckAuxSubtitlesFile(clipInfo,&dwSubtitlesFileAddress,&dwSubtitlesFileSize,&pfParseSubtitles, wSubtitleID))
  167. #else
  168. if ( FALSE == findAndCheckAuxSubtitlesFile(clipInfo,&dwSubtitlesFileAddress,&dwSubtitlesFileSize,&pfParseSubtitles/*, &sfFormatID */))
  169. #endif
  170.  {
  171. // >>> Robin_0903_2004
  172. dbg_printf(("initAuxSubtitles - Auxiliary subtitles file wasn't foundn"));
  173. #ifdef SUPPORT_FLASH_CARD
  174. if (IS_PLAYING_CARD)
  175. bReadAuxSubtitle = FALSE;
  176. #endif
  177. return FALSE;
  178. }
  179. // _mpeg4ExternalSubtitleAddr = _dwMPEG4ProcessingEndAddr;
  180. #ifdef DEBUG_AUX_SUBTITLES
  181.    dwEnd=gen_timer();
  182.    dbg_printf(("Subtitles finding & probing time: %lun",dwEnd-dwStart));
  183. #endif
  184.    // if so, parse it and store its content.
  185. if ( FALSE == pfParseSubtitles(dwSubtitlesFileAddress,dwSubtitlesFileSize,dwScale,dwRate)) {
  186. tr_printf(("initAuxSubtitles - Couldn't parse subtitles filen"));
  187. #ifdef DEBUG_AUX_SUBTITLES
  188.     dwEnd=gen_timer();
  189.     dbg_printf(("Total subtitles handling time: %lun",dwEnd-dwStart));
  190. #endif
  191. #ifdef SUPPORT_FLASH_CARD
  192. if (IS_PLAYING_CARD)
  193. bReadAuxSubtitle = FALSE;
  194. #endif
  195. return FALSE;
  196. }
  197. // Robin_0527_2004_A
  198. _dwMPEG4ProcessingEndAddr = (CALC_SUBTITLE_ADDRESS( _mpeg4ExternalSubtitleAddr, g_pSubtitleStorage->dwCurrentStorageOffset) >>9) <<9;
  199. _dwMPEG4ProcessingEndAddr = (_dwMPEG4ProcessingEndAddr>>9)<<9;
  200.  
  201. dbg_printf(("Start Address of Current External Subtitle : 0x%lxn",_dwMPEG4ProcessingEndAddr));
  202. subtitleStorageInitReading();
  203.    subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK);
  204.    SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  205.    SET_AUX_SUBTITLE_BUFFER_LOCKED(FALSE);
  206.    SET_AUX_SUBTITLE_AVAILABE(TRUE);
  207.    setSubtitlesPlayMode(TRUE);
  208. //   g_dwSubtitleTimingOffset = 0;
  209. #ifdef DEBUG_AUX_SUBTITLES
  210.    dwEnd=gen_timer();
  211.    dbg_printf(("Total subtitles handling time: %lun",dwEnd-dwStart));
  212. #endif
  213.    // initialize interrupt handlers?
  214. #ifdef SUPPORT_FLASH_CARD
  215. if (IS_PLAYING_CARD)
  216. bReadAuxSubtitle = FALSE;
  217. #endif
  218. return TRUE;
  219. }
  220. /////////////////////////////////////////////////////////////////////////////////////////////
  221. // Function name : findAndCheckAuxSubtitlesFile
  222. // Purpose : looks for a subtitle file for the given clip
  223. // Input Parameters : clipInfo  - Information about the clip for which
  224. //    to look for subtitles
  225. // Output Parameters: dwSubtitlesFileAddress - Start address of the 1st subtitles file that was found
  226. //   dwSubtitlesFileSize  - Size of the subtitles 1st file that was found
  227. //   pfParse  - The parsing function used by the detected format
  228. //    of the 1st recognized subtitle file.
  229. //    prParse=NULL if none was found.
  230. // Return type : TRUE if recognized subtitles were found, FALSE otherwise.
  231. // Description : The function looks for files which have the same name (only name, not extension)
  232. //   as the given clip, and tests if they are recognized subtitle files.
  233. //   It then determines the format of the 1st such file.
  234. /////////////////////////////////////////////////////////////////////////////////////////////
  235. // <<< Robin_0903_2004
  236. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  237. BOOL findAndCheckAuxSubtitlesFile(ClipFileInfo *clipInfo,DWORD *dwSubtitlesFileAddress,
  238.   DWORD *dwSubtitlesFileSize,SubtitleParsingFuncPtr *pfParse, WORD wSubtitleID)
  239. #else
  240. BOOL findAndCheckAuxSubtitlesFile(ClipFileInfo *clipInfo,DWORD *dwSubtitlesFileAddress,
  241.   DWORD *dwSubtitlesFileSize,SubtitleParsingFuncPtr *pfParse)
  242. #endif
  243. // >>> Robin_0903_2004
  244. {
  245. // Robin_0527_2004_A, change the process of checking a subtitle file, change the memory allocate of subtitle
  246. // subtitle file name: avi_file_name + .SRT/.SUB/.SMI/..
  247. // limition:
  248. // 1) only support .SRT(SubRip)/.SUB(MicroDVD)/.TXT(MicroDVD)/.SMI(SAMI)/.SUB(SubViewer2.0)
  249. //   .SSA(SubStation Alpha)/.ASS(Advanced SubStation Alpha)/.PSB(PowerDivX)/.TXT(TMPlayer)
  250. // 2) only support one external subtitle and no exist of internal subtitle
  251. // 3) only support western/central european language
  252. // 4) if USE_AUX_SUBTITLES, the cpu code size will exceed 1M(need SUPPORT_2M_FLASH)
  253. // 5) the max size of subtitle in memory is 200KB (SUBTITLES_MEMORY_SIZE)
  254. // 6) the max size of avi file name is  65
  255. // Robin_0715_2004, merge changelist #24166
  256. #if 1
  257. // <<< Robin_0903_2004
  258. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  259. if(clipInfo->wSubFileCnt == 0 ||clipInfo->wSubFileCnt <= wSubtitleID )
  260. return FALSE;
  261. else
  262. {
  263. int i,j;
  264. Extend_Subtitle_Info_St SubtitleInfo;
  265. BOOL bAuxSubtitle = FALSE;
  266. SubtitleType auxSubtitleType;
  267. sc_GetBytes( SC_AVI_EXTEND_SUBTITLE_ADDR,
  268.        ( ((clipInfo->wSubFileIndex)+wSubtitleID) * sizeof(Extend_Subtitle_Info_St) ),
  269.        sizeof(Extend_Subtitle_Info_St),
  270.        (BYTE*)&SubtitleInfo );
  271. *dwSubtitlesFileAddress = SubtitleInfo.dwSubtitlesFileAddress;
  272. // <<< Robin_1003_2004_E
  273. *dwSubtitlesFileSize = SubtitleInfo.dwSubtitlesFileSize;
  274. #ifdef SUPPORT_FLASH_CARD //JERRYC_2004_Oct_21
  275. if(IS_PLAYING_CARD)
  276. {
  277. STRUCT_FILE *pfile = FCU_TEMP_SUBTITLE_FILE_STRCUT_ADDR;
  278.       //Is *dwSubtitlesFileAddress the real subtitle file start address?
  279. FileSys_FileOpen(pfile, *dwSubtitlesFileAddress, 0, *dwSubtitlesFileSize);
  280. }
  281. #endif
  282. for (j=0;j<SF_NUMBER_OF_FORMATS;j++)
  283. {
  284. if ( NULL != availableSubtitleFormats[j].pfProbe)
  285. {
  286. if (TRUE == availableSubtitleFormats[j].pfProbe(*dwSubtitlesFileAddress, *dwSubtitlesFileSize))
  287. {
  288. *pfParse=availableSubtitleFormats[j].pfParse;
  289. bAuxSubtitle = TRUE;
  290. auxSubtitleType = j+EXTERNAL_SUBP;
  291. break;
  292. }
  293. }
  294. }
  295. // >>> Robin_1003_2004_E
  296. if (bAuxSubtitle == TRUE)
  297. {
  298. // <<< Robin_0907_2004
  299. if (auxSubtitleType != SAMI && auxSubtitleType != EXTERNAL_SUBP)
  300. {
  301. // Robin_1119_2004, unknown auxsubtitle language
  302. memset(&_mpeg4SubtitleStreamInfo, 0, sizeof(MPEG4SubtitleStreamInfo));
  303. _mpeg4SubtitleStreamID = NO_STREAM;
  304. _mpeg4SubtitleType = auxSubtitleType;
  305. sc_SetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  306. (SI_CLIPS_SUB_AVAILABLE_NUM * SIZE_OF_SUBTITLE_STREAM_INFO),
  307. SIZE_OF_SUBTITLE_STREAM_INFO,
  308. (BYTE*)&_mpeg4SubtitleStreamInfo
  309.      );
  310.       
  311. SI_CLIPS_SUB_AVAILABLE_NUM ++;
  312. }
  313.       }
  314. // >>> Robin_0907_2004
  315. return bAuxSubtitle;
  316. }
  317. #else
  318. int i,j;
  319. // <<< Robin_1003_2004_E
  320. if ((NULL != clipInfo->dwSubtitlesFileAddress) && (NULL != clipInfo->dwSubtitlesFileSize))
  321. {
  322. *dwSubtitlesFileAddress = clipInfo->dwSubtitlesFileAddress;
  323. *dwSubtitlesFileSize = clipInfo->dwSubtitlesFileSize;
  324. for (j=0;j<SF_NUMBER_OF_FORMATS;j++)
  325. {
  326. if ( NULL != availableSubtitleFormats[j].pfProbe)
  327. {
  328. if (TRUE == availableSubtitleFormats[j].pfProbe(*dwSubtitlesFileAddress, *dwSubtitlesFileSize))
  329. {
  330. *pfParse=availableSubtitleFormats[j].pfParse;
  331. return TRUE;
  332. }
  333. }
  334. }
  335. }
  336. // >>> Robin_1003_2004_E
  337. return FALSE;
  338. #endif
  339. // >>> Robin_0903_2004
  340. #else
  341. #define AUXSUBTITLE_MAX_FILENAME_LEN 65 // same as szFileID[65]
  342. WCHAR szFilename [AUXSUBTITLE_MAX_FILENAME_LEN];
  343.     LPCWSTR *i_aValidExtensions;
  344. unsigned int FsType;
  345.     int i,j;
  346.     BOOL bFindAuxSubtitlesFile = FALSE;
  347. int FileNameLength;
  348. FsType = FileSys_determineType();
  349. if (FileSys_selectType(FsType) && FileSys_initialize(TRUE))
  350. {
  351. if (FALSE == FileSys_changeDir(clipInfo->szDirectoryName))
  352. {
  353. return FALSE;
  354. }
  355. memset(&szFilename, 0, AUXSUBTITLE_MAX_FILENAME_LEN<<1);
  356. wcsncpy(szFilename,clipInfo->szFilename,wcslen(clipInfo->szFilename));
  357. if (CLIPS_MAX_FILENAME_LEN <= wcslen(clipInfo->szFilename))
  358. {
  359. if (FileSys_fileExists(szFilename)) 
  360. {
  361. FindData fdInfo;
  362. UINT16 hFileFind= FileSys_findFirstFile(szFilename, &fdInfo);
  363. if (NULL == hFileFind) 
  364. return FALSE;
  365. do {
  366. if (fdInfo.dwStartAddr == clipInfo->dwFileLocation)
  367. {
  368. LPWSTR pszDelim;
  369. memset(&szFilename, 0, AUXSUBTITLE_MAX_FILENAME_LEN<<1);
  370. pszDelim= wcsrchr(fdInfo.szFileID, '.');
  371. wcsncpy(szFilename, fdInfo.szFileID, (int)(pszDelim - fdInfo.szFileID));
  372. break;
  373. }
  374. } while (FileSys_findNextFile(hFileFind, &fdInfo));
  375. FileSys_findClose(hFileFind);
  376. }
  377.             
  378. }
  379. FileNameLength = wcslen(szFilename);
  380. for (i=0; i< SF_NUMBER_OF_FORMATS; i++)
  381. {
  382. i_aValidExtensions = availableSubtitleFormats[i].aFormatValidExtensions;
  383. for (j=0;NULL != i_aValidExtensions[j];j++)
  384. {
  385. wcsncat(szFilename, i_aValidExtensions[j],wcslen(i_aValidExtensions[j]));
  386. if (FileSys_fileExists(szFilename)) 
  387. {
  388. FindData fdInfo;
  389. UINT16 hFileFind= FileSys_findFirstFile(szFilename, &fdInfo);
  390. if (NULL != hFileFind) 
  391. {
  392. dbg_printf(("The subtitle file is found.n"));
  393. *dwSubtitlesFileAddress= fdInfo.dwStartAddr;
  394. *dwSubtitlesFileSize= (DWORD)fdInfo.cbFileSizeLow;
  395. if ( NULL != availableSubtitleFormats[i].pfProbe)
  396. {
  397. if (TRUE == availableSubtitleFormats[i].pfProbe(*dwSubtitlesFileAddress, *dwSubtitlesFileSize))
  398. *pfParse=availableSubtitleFormats[i].pfParse;
  399. else
  400. continue;
  401. }
  402. *pfParse=availableSubtitleFormats[i].pfParse;
  403. FileSys_findClose(hFileFind);
  404. return TRUE;
  405. }
  406. }
  407. memset(&szFilename[FileNameLength], 0, wcslen(i_aValidExtensions[j])<<1);
  408. }
  409. }
  410. }     
  411. return FALSE;
  412. #endif
  413. }
  414. void findAuxSubtitlesFile(Clip *pClip, const FindData *i_pFileInfo)
  415. {
  416. if ((eClipType_AVI == (pClip->m_pConstAttr)->m_eType)
  417. #ifdef IS_ASF_CAPABLE
  418. || (eClipType_ASF == (pClip->m_pConstAttr)->m_eType)
  419. #endif
  420. #ifdef IS_MP4_CAPABLE
  421. || (eClipType_MP4 == (pClip->m_pConstAttr)->m_eType)
  422. #endif
  423. )
  424. {
  425. int i,j;
  426. LPCWSTR *i_aValidExtensions;
  427. LPWSTR pszDelim;
  428. WCHAR szFilename [65];
  429. int FileNameLength;
  430. pszDelim= wcsrchr(i_pFileInfo->szFileID, '.');
  431. memset(&szFilename, 0, 65<<1);
  432. wcsncpy(szFilename, i_pFileInfo->szFileID, (int)(pszDelim - i_pFileInfo->szFileID+1));
  433. FileNameLength = wcslen(szFilename);
  434. // Robin_1112_2004, "*" mean any char/string
  435. #if 1 //MikeX_1213_2004_A
  436. wcsncat(szFilename, FILESYS_WILDCARD_SEARCH, sizeof(WCHAR));
  437. #endif
  438. // <<< Robin_0903_2004
  439. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  440. (pClip->m_cfiInfo).wSubFileIndex = _mpeg4TotalSubtitleNum;
  441. (pClip->m_cfiInfo).wSubFileCnt = 0;
  442. #else
  443. (pClip->m_cfiInfo).dwSubtitlesFileAddress = NULL;
  444. // Robin_1003_2004_E
  445. (pClip->m_cfiInfo).dwSubtitlesFileSize = NULL;
  446. #endif
  447. // Robin_0730_2004, improve the speed of findAuxSubtitlesFile()
  448. {
  449. FindData fdInfo;
  450. UINT16 hFileFind= FileSys_findFirstFile(szFilename, &fdInfo);
  451. if (NULL == hFileFind) 
  452. {
  453. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  454. (pClip->m_cfiInfo).wSubFileIndex = 0;
  455. #endif
  456. return;
  457. }
  458. do {
  459. // Robin_1125_2004, if subtitle filesize larger than 1MB, not supported
  460. if (fdInfo.cbFileSizeLow > 1000000UL) // if filesize is larger than 1MB, not text subtitle
  461. continue;
  462. #ifdef SUPPORT_FLASH_CARD
  463. if(IS_PLAYING_CARD){
  464.                if(0 != wcsncmp(fdInfo.szFileID, i_pFileInfo->szFileID, FileNameLength))
  465.                 continue;
  466. }
  467. #endif
  468. // <<< Robin_1003_2004_E
  469. if (GenericClip_isKindOf(fdInfo.szFileID, CLIP_VALID_EXTENSIONS(SUB)))
  470. {
  471. #ifdef DIVX_SUPPORT_MULTI_SUBTITLE
  472. Extend_Subtitle_Info_St foundSubtitle;
  473. foundSubtitle.dwSubtitlesFileAddress = fdInfo.dwStartAddr;
  474. foundSubtitle.dwSubtitlesFileSize = fdInfo.cbFileSizeLow;
  475. sc_SetBytes( SC_AVI_EXTEND_SUBTITLE_ADDR,
  476.        (_mpeg4TotalSubtitleNum * sizeof(Extend_Subtitle_Info_St) ),
  477.        sizeof(Extend_Subtitle_Info_St),
  478.        (BYTE*)&foundSubtitle );
  479. (pClip->m_cfiInfo).wSubFileCnt ++;
  480. _mpeg4TotalSubtitleNum++;
  481. #else
  482. FileSys_findClose(hFileFind);
  483. (pClip->m_cfiInfo).dwSubtitlesFileAddress = fdInfo.dwStartAddr;
  484. (pClip->m_cfiInfo).dwSubtitlesFileSize = fdInfo.cbFileSizeLow;
  485. break;
  486. #endif
  487. // <<< Robin_0903_2004
  488. }
  489. // >>> Robin_1003_2004_E
  490. } while (FileSys_findNextFile(hFileFind, &fdInfo));
  491. FileSys_findClose(hFileFind);
  492. #ifdef SUPPORT_FLASH_CARD
  493. if(IS_PLAYING_CARD){
  494. FileSys_findFirstFile(i_pFileInfo->szFileID, &fdInfo);
  495.          }
  496. #endif
  497. }
  498. }
  499. return;
  500. }
  501. /////////////////////////////////////////////////////////////////////////////////////////////
  502. // Function Name : subtitleStorageInitWriting
  503. // Purpose : Initializes the interface to the subtitles storage
  504. // Return type : void
  505. // Description :
  506. /////////////////////////////////////////////////////////////////////////////////////////////
  507. void subtitleStorageInitWriting(void)
  508. {
  509. // <<< Stivenz_1115_04: Memory optimization: Move g_SubtitleStorage and g_SubtitleIndex to heap.
  510. if(!_allocateStorageInterface())
  511. return;
  512. // Stivenz_1115_04 >>>
  513. memset(g_pSubtitleStorage,0,sizeof(SubtitleStorageInterface));
  514. #ifdef AUX_SUBTITLES_INDEX
  515. // <<< Stivenz_1115_04: Memory optimization: Move g_SubtitleStorage and g_SubtitleIndex to heap.
  516. if(!_allocateStorageIndex())
  517. return;
  518. // Stivenz_1115_04 >>>
  519.    memset(g_pSubtitleIndex,0,sizeof(SubtitleStorageIndex));
  520.    g_pSubtitleIndex->wInterval = 1;
  521. #endif // AUX_SUBTITLES_INDEX
  522. }
  523. /////////////////////////////////////////////////////////////////////////////////////////////
  524. // Function Name : subtitleStorageInitReading
  525. // Purpose : Initializes the interface to the subtitles storage
  526. // Return type : void
  527. // Description :
  528. /////////////////////////////////////////////////////////////////////////////////////////////
  529. void subtitleStorageInitReading(void)
  530. {
  531. // <<< Stivenz_1115_04: Memory optimization: Move g_SubtitleStorage and g_SubtitleIndex to heap.
  532. if(!_allocateStorageInterface())
  533. return;
  534. // Stivenz_1115_04 >>>
  535. memset(g_pSubtitleStorage,0,sizeof(SubtitleStorageInterface));
  536.    subtitleStorageFillBuffer();
  537. }
  538. /////////////////////////////////////////////////////////////////////////////////////////////
  539. // Function Name : subtitleStorageMarkLastEntry
  540. // Purpose : to be used after the last subtitle was parsed.
  541. // Return type : TRUE - on success. FALSE when out of subtitle storage memory
  542. // Description : writes LAST_SUBTITLE_MARKER to the next position in the subtitle
  543. //    storage.
  544. /////////////////////////////////////////////////////////////////////////////////////////////
  545. BOOL subtitleStorageMarkLastEntry(void)
  546. {
  547. if (!subtitleStorageWriteDWORD(LAST_SUBTITLE_MARKER))
  548. return FALSE;
  549.    subtitleStorageCommitBuffer();
  550. #ifdef _DEBUG
  551. dbg_printf(("Byte count: %lun",g_pSubtitleStorage->dwByteCount));
  552. dbg_printf(("Entry count: %lun",g_pSubtitleStorage->dwEntryCount));
  553. dbg_printf(("Max entry length: %un",g_pSubtitleStorage->wMaxEntryLength));
  554.    dbg_printf(("Max line length: %un",g_pSubtitleStorage->wMaxLineLength));
  555. #endif //_DEBUG
  556. return TRUE;
  557. }
  558. /////////////////////////////////////////////////////////////////////////////////////////////
  559. // Function Name : subtitleStorageStartEntry
  560. // Purpose : Opens a new subtitle entry
  561. // Input Parameters : dwStartSCLK - Display starting time (SCLK)
  562. // Return type : TRUE - on success. FALSE when out of subtitle storage memory
  563. // Description : writes the SCLK DWORD, followed by a null byte
  564. /////////////////////////////////////////////////////////////////////////////////////////////
  565. BOOL subtitleStorageStartEntry(DWORD dwStartSCLK)
  566. {
  567. dwStartSCLK = (dwStartSCLK > AUX_SUBTITLE_EARLY_DISPLAY_OFFSET) ? (dwStartSCLK - AUX_SUBTITLE_EARLY_DISPLAY_OFFSET) : 0;
  568. #ifdef AUX_SUBTITLES_INDEX
  569.    updateSubtitlesIndex(g_pSubtitleStorage->dwCurrentStorageOffset +
  570.     g_pSubtitleStorage->wBufferPos, dwStartSCLK);
  571. #endif // AUX_SUBTITLES_INDEX
  572. if (!subtitleStorageWriteDWORD(dwStartSCLK))
  573. return FALSE;
  574. if (!subtitleStorageWriteByte(0))
  575. return FALSE;
  576. #ifdef _DEBUG
  577. g_pSubtitleStorage->wCurrentEntryLength = 0;
  578.    g_pSubtitleStorage->wCurrentLineLength = 0;
  579. #endif //_DEBUG
  580. return TRUE;
  581. }
  582. /////////////////////////////////////////////////////////////////////////////////////////////
  583. // Function Name : subtitleStorageEndEntry
  584. // Purpose : Closes a subtitle entry
  585. // Input Parameters : dwEndSCLK - Display starting time (SCLK)
  586. // Return type : TRUE - on success. FALSE when out of subtitle storage memory
  587. // Description : writes a null byte, followed by the SCLK DWORD.
  588. /////////////////////////////////////////////////////////////////////////////////////////////
  589. BOOL subtitleStorageEndEntry(DWORD dwEndSCLK)
  590. {
  591. dwEndSCLK = (dwEndSCLK > AUX_SUBTITLE_EARLY_DISPLAY_OFFSET) ? (dwEndSCLK - AUX_SUBTITLE_EARLY_DISPLAY_OFFSET) : 0;
  592. #ifdef _DEBUG
  593. g_pSubtitleStorage->dwEntryCount++;
  594. if ( g_pSubtitleStorage->wCurrentEntryLength > g_pSubtitleStorage->wMaxEntryLength )
  595. g_pSubtitleStorage->wMaxEntryLength = g_pSubtitleStorage->wCurrentEntryLength;
  596.    if ( g_pSubtitleStorage->wCurrentLineLength > g_pSubtitleStorage->wMaxLineLength )
  597. g_pSubtitleStorage->wMaxLineLength = g_pSubtitleStorage->wCurrentLineLength;
  598. #endif //_DEBUG
  599. if (!subtitleStorageWriteByte(0))
  600. return FALSE;
  601. if (!subtitleStorageWriteDWORD(dwEndSCLK))
  602. return FALSE;
  603. return TRUE;
  604. }
  605. /////////////////////////////////////////////////////////////////////////////////////////////
  606. // Function Name : subtitleStorageWriteByte
  607. // Purpose : Writes a byte to the subtitle storage memory
  608. // Input Parameters : b       - the byte to be stored
  609. // Return type : TRUE - on success. FALSE when out of subtitle storage memory
  610. // Description : writes the byte to the internal buffer. when full - writes the buffer
  611. //                  to the subtitle storage memory
  612. /////////////////////////////////////////////////////////////////////////////////////////////
  613. BOOL subtitleStorageWriteByte(BYTE b)
  614. {
  615. if (g_pSubtitleStorage->dwCurrentStorageOffset + g_pSubtitleStorage->wBufferPos  >= SUBTITLES_MEMORY_SIZE)
  616. return FALSE;
  617. g_pSubtitleStorage->baBuffer[g_pSubtitleStorage->wBufferPos++] = b;
  618. if ( g_pSubtitleStorage->wBufferPos >= STORAGE_INTERFACE_BUFFER_SIZE )
  619. subtitleStorageCommitBuffer();
  620. #ifdef _DEBUG
  621. g_pSubtitleStorage->dwByteCount++;
  622.    g_pSubtitleStorage->wCurrentEntryLength++;
  623.    g_pSubtitleStorage->wCurrentLineLength++;
  624. #endif
  625. return TRUE;
  626. }
  627. /////////////////////////////////////////////////////////////////////////////////////////////
  628. // Function Name : subtitleStorageWriteDWORD
  629. // Purpose : Writes a double word to the subtitle storage memory
  630. // Input Parameters : dw       - the dword to be stored
  631. // Return type : TRUE - on success. FALSE when out of subtitle storage memory
  632. // Description : writes the word to the internal buffer, byte by byte. when
  633. //                  the internal buffer is full - writes the buffer
  634. //                  to the subtitle storage memory
  635. /////////////////////////////////////////////////////////////////////////////////////////////
  636. BOOL subtitleStorageWriteDWORD(DWORD dw)
  637. {
  638. int i;
  639. for (i=0;i<4;i++) {
  640.       // write the high byte
  641. if (!subtitleStorageWriteByte(dw >> 24 ))
  642. return FALSE;
  643. dw = dw << 8 ;
  644. }
  645. return TRUE;
  646. }
  647. /////////////////////////////////////////////////////////////////////////////////////////////
  648. // Function Name : subtitleStorageCommitBuffer
  649. // Purpose : Internal Write the internal buffer to memory
  650. // Return type : void
  651. // Description : uses sc_SetBytes to write the buffer to subtitle memory. resets wBufferPos
  652. /////////////////////////////////////////////////////////////////////////////////////////////
  653. void subtitleStorageCommitBuffer(void)
  654. {
  655.    wai_sem(SEM_DRAM_ID);
  656. // Robin_0527_2004_A
  657.    I49_WriteDRAMData (CALC_SUBTITLE_ADDRESS(_mpeg4ExternalSubtitleAddr , g_pSubtitleStorage->dwCurrentStorageOffset),
  658.      (UINT16*)g_pSubtitleStorage->baBuffer, STORAGE_INTERFACE_BUFFER_SIZE/2);
  659.    sig_sem(SEM_DRAM_ID);
  660. g_pSubtitleStorage->dwCurrentStorageOffset += g_pSubtitleStorage->wBufferPos;
  661.    g_pSubtitleStorage->wBufferPos = 0;
  662. }
  663. /////////////////////////////////////////////////////////////////////////////////////////////
  664. // Function Name : subtitleStorageGetSubtitle
  665. // Purpose : Get a subtitle string and the end sclk count
  666. // Output Parameters:  dwEndSCLK - The time for stopping the display of this subtitle in SCLK count
  667. // Return type : TRUE on success, FALSE if string is too long to fit in buffer
  668. // Description : Copies the subtitle string from subtitles storage memory to
  669. //                  the scratch pad. The string is copied as it was in the subtitles file,
  670. //   except for conversion of formatting symbols. Conversion to Unicode or any
  671. //                  other format the OSD module requires, is likely to be language-dependant,
  672. //                  and should be performed by the calling function if necessary.
  673. //   The time for displaying the returned subtitle should be determined beforehand,
  674. //                  and this function should be called when this time is reached. The end time is
  675. //                  returned by this function.
  676. /////////////////////////////////////////////////////////////////////////////////////////////
  677. BOOL subtitleStorageGetSubtitle(DWORD *dwEndSCLK)
  678. {
  679. int sc_pos = 0;
  680.    int copyStart;
  681.    BYTE c;
  682.    int i=0;
  683.    // skip the null byte
  684. subtitleStorageReadByte(&c);
  685. // save start address of the segment to be written to the scratch pad
  686. copyStart = g_pSubtitleStorage->wBufferPos;
  687.    do
  688.    {
  689.   c = g_pSubtitleStorage->baBuffer[g_pSubtitleStorage->wBufferPos++];
  690. if ( g_pSubtitleStorage->wBufferPos >= STORAGE_INTERFACE_BUFFER_SIZE )
  691.       {
  692.        sc_SetBytes(SC_AUX_SUBTITLES_STRINGS_ADDR,
  693.           sc_pos,
  694.                      g_pSubtitleStorage->wBufferPos - copyStart,
  695.                      &(g_pSubtitleStorage->baBuffer[copyStart]) );
  696.          sc_pos += g_pSubtitleStorage->wBufferPos - copyStart;
  697. subtitleStorageFillBuffer();
  698.          copyStart = g_pSubtitleStorage->wBufferPos;
  699.       }
  700.       i++;
  701.    }
  702.    while ( '' != c && i < SUBTITLE_STRING_SC_SZ_B );
  703.    // if subtitle text is longer than the subtitle string buffer
  704.    if ( i == SUBTITLE_STRING_SC_SZ_B ) {
  705.       // read until the terminating null
  706.     while ( '' != c )
  707.        subtitleStorageReadByte(&c);
  708. // terminate the string
  709. if (copyStart != g_pSubtitleStorage->wBufferPos)
  710.       {
  711. // the end of the string wasn't written to the scratch pad yet
  712.        c = g_pSubtitleStorage->baBuffer[g_pSubtitleStorage->wBufferPos-1];
  713.          g_pSubtitleStorage->baBuffer[g_pSubtitleStorage->wBufferPos-1] = '';
  714.       }
  715.       else
  716.       {
  717. BYTE tmp[2];
  718.        // the last char was alraedy written, so write directly to the scratch pad
  719. sc_GetBytes(SC_AUX_SUBTITLES_STRINGS_ADDR,
  720.       (sc_pos)-1,
  721.                2,
  722.                tmp );
  723.                tmp[1]='';
  724. sc_SetBytes(SC_AUX_SUBTITLES_STRINGS_ADDR,
  725.       (sc_pos)-1,
  726.                2,
  727.                tmp );
  728.       }
  729.       dbg_printf(("End SCLK %lun",*dwEndSCLK));
  730.    }
  731. // if some characters weren't yet copied to the scratch pad
  732. if (copyStart != g_pSubtitleStorage->wBufferPos)
  733.    {
  734.    sc_SetBytes(SC_AUX_SUBTITLES_STRINGS_ADDR,
  735.       sc_pos,
  736.                 g_pSubtitleStorage->wBufferPos - copyStart,
  737.                 &(g_pSubtitleStorage->baBuffer[copyStart]) );
  738. if ( i == SUBTITLE_STRING_SC_SZ_B )
  739.       {
  740. // resotre the character that was replaced by ''
  741.     g_pSubtitleStorage->baBuffer[g_pSubtitleStorage->wBufferPos-1] = c;
  742.       }
  743.    }
  744.    
  745.    // read end SCLK value
  746.    subtitleStorageReadDWORD(dwEndSCLK);
  747.    return ( i != SUBTITLE_STRING_SC_SZ_B ); 
  748. }
  749. /////////////////////////////////////////////////////////////////////////////////////////////
  750. // Function Name : subtitleStorageSkipSubtitle
  751. // Purpose : Go to the next subtitle, and get the start SCLK count
  752. // Output Parameters: dwStartSCLK - Start display time, as SCLK count
  753. // Description : 
  754. /////////////////////////////////////////////////////////////////////////////////////////////
  755. BOOL subtitleStorageSkipSubtitle(DWORD *dwStartSCLK)
  756. {
  757.    BYTE c;
  758.    // skip the null byte
  759.    subtitleStorageReadByte(&c);
  760.    // skip the string
  761.    do
  762.    {
  763.     subtitleStorageReadByte(&c);
  764.    } while ( c != '' );
  765.    // skip end SCLK value
  766.    subtitleStorageReadDWORD(dwStartSCLK);
  767. return subtitleStorageGetStartTime(dwStartSCLK);
  768. }
  769. /////////////////////////////////////////////////////////////////////////////////////////////
  770. // Function Name : subtitleStorageGetStartTime
  771. // Purpose : Get the start SCLK count of the current subtitle
  772. // Output Parameters: dwStartSCLK - Start display time, as SCLK count
  773. // Return type : FALSE if there are no more subtitles. TRUE otherwise
  774. // Description : Reads the start SCLK count for this subtitle. If there are no more subtitle,
  775. //                  FALSE is returned, and also the value of dwStartSCLK is LAST_SUBTITLE_MARKER
  776. //   which is set to be the max possible value of the SCLK
  777. /////////////////////////////////////////////////////////////////////////////////////////////
  778. BOOL subtitleStorageGetStartTime(DWORD *dwStartSCLK)
  779. {
  780. subtitleStorageReadDWORD(dwStartSCLK);
  781.    if (LAST_SUBTITLE_MARKER == *dwStartSCLK) {
  782.     subtitleStorageRewindBytes(4);
  783.       return FALSE;
  784.    }
  785.     return TRUE;
  786. }
  787. /////////////////////////////////////////////////////////////////////////////////////////////
  788. // Function Name : subtitleStorageFillBuffer
  789. // Purpose : Internal function for reading from the subtitles memory in to the internal buffer
  790. // Input Parameters : storage - handle to a storage struct
  791. // Return type : void
  792. // Description : uses sc_GetBytes to write the buffer to subtitle memory. resets wBufferPos
  793. /////////////////////////////////////////////////////////////////////////////////////////////
  794. void subtitleStorageFillBuffer(void)
  795. {
  796.    wai_sem(SEM_DRAM_ID);
  797.    I49_ReadDRAMData(CALC_SUBTITLE_ADDRESS(_mpeg4ExternalSubtitleAddr , g_pSubtitleStorage->dwCurrentStorageOffset),
  798.                         (UINT16 *)g_pSubtitleStorage->baBuffer , STORAGE_INTERFACE_BUFFER_SIZE/2);
  799.    sig_sem(SEM_DRAM_ID);
  800. g_pSubtitleStorage->dwCurrentStorageOffset += STORAGE_INTERFACE_BUFFER_SIZE;
  801.    g_pSubtitleStorage->wBufferPos = 0;
  802. }
  803. /////////////////////////////////////////////////////////////////////////////////////////////
  804. // Function Name : subtitleStorageReadByte
  805. // Purpose : Reads a byte to the subtitle storage memory
  806. // Input Parameters : b       - place to store the byte
  807. // Return type : void
  808. // Description : Reads the byte from the internal buffer. when empty - fills the buffer
  809. /////////////////////////////////////////////////////////////////////////////////////////////
  810. void subtitleStorageReadByte(BYTE *b)
  811. {
  812. *b = g_pSubtitleStorage->baBuffer[g_pSubtitleStorage->wBufferPos++];
  813. if ( g_pSubtitleStorage->wBufferPos >= STORAGE_INTERFACE_BUFFER_SIZE )
  814. subtitleStorageFillBuffer();
  815. }
  816. /////////////////////////////////////////////////////////////////////////////////////////////
  817. // Function Name : subtitleStorageReadDWORD
  818. // Purpose : Reads a byte to the subtitle storage memory
  819. // Input Parameters : b       - place to store the DWOR
  820. // Return type : void
  821. // Description : Reads the DWORD byte by byte using subtitleStorageReadByte
  822. /////////////////////////////////////////////////////////////////////////////////////////////
  823. void subtitleStorageReadDWORD(DWORD *dw)
  824. {
  825. int i;
  826.    BYTE b;
  827.    *dw = 0;
  828. for (i=0;i<4;i++) {
  829. subtitleStorageReadByte(&b);
  830.       (*dw) = (*dw) << 8 ;
  831.       (*dw) += (DWORD)b;
  832. }
  833. }
  834. /////////////////////////////////////////////////////////////////////////////////////////////
  835. // Function Name  : subtitleStorageRewindBytes
  836. // Purpose  : Rewinds the subtitles storage pointer
  837. // Input Parameters: count   - number of bytes to rewind
  838. // Return type : FALSE when attempting to rewind beyond the start of the subtitles storage
  839. //   TRUE otherwise.
  840. // Description : Checks if the requested position is currently in the buffer, and updates
  841. //                  internal pointers if so. Otherwise, reads required data from the SDRAM
  842. /////////////////////////////////////////////////////////////////////////////////////////////
  843. BOOL subtitleStorageRewindBytes(WORD count)
  844. {
  845.    BYTE bAlign=0;
  846. if ( g_pSubtitleStorage->dwCurrentStorageOffset - STORAGE_INTERFACE_BUFFER_SIZE
  847.     + g_pSubtitleStorage->wBufferPos < count )
  848.     return FALSE;
  849.    else if ( g_pSubtitleStorage->wBufferPos >= count )
  850.     g_pSubtitleStorage->wBufferPos -= count;
  851.    else {
  852.     g_pSubtitleStorage->dwCurrentStorageOffset -= (STORAGE_INTERFACE_BUFFER_SIZE + count - g_pSubtitleStorage->wBufferPos);
  853.       g_pSubtitleStorage->wBufferPos=0;
  854.       bAlign = g_pSubtitleStorage->dwCurrentStorageOffset & 0x3 ;
  855.     g_pSubtitleStorage->dwCurrentStorageOffset -= bAlign;
  856.       subtitleStorageFillBuffer();
  857.       g_pSubtitleStorage->wBufferPos = bAlign;
  858.    }
  859.    return TRUE;
  860. }
  861. /////////////////////////////////////////////////////////////////////////////////////////////
  862. // Function Name  : checkAndHandleAuxSubtitles
  863. // Purpose  : Reads subtitles from memory, and sends them to the UI
  864. // when it's time to display them.
  865. // Input Parameters: dwCurrentTime - current SCLK count.
  866. // Return type : void
  867. // Description : Checks if the current time is later than the previously
  868. //                  noted "next update time". If it's time to start displaying
  869. //   a new subtitle, and the UI task has finished dealing with
  870. //   the previous subtitle, write the new subtitle text to a buffer
  871. //   and send an event to the UI - to start displaying it.
  872. //   if it's time to stop displaying a subtitle - send a proper
  873. //   event to the UI.
  874. /////////////////////////////////////////////////////////////////////////////////////////////
  875. void checkAndHandleAuxSubtitles(DWORD dwCurrentTime)
  876. {
  877.    if ( !IS_AUX_SUBTITLE_PLAY_MODE )
  878.     return;
  879. while ( dwCurrentTime >= g_dwNextSubtitleUpdateSCLK )
  880.    {
  881.     if ( IS_AUX_SUBTITLE_START_DISPLAY ) {
  882.        // the start SCLK was read, and now this time was reached.
  883.          // display the subtitle
  884.          // if the UI task finished with the previous subtitles, read a new one and tell the UI
  885.          if ( FALSE == IS_AUX_SUBTITLE_BUFFER_LOCKED ) {
  886.           if ( FALSE == subtitleStorageGetSubtitle(&g_dwNextSubtitleUpdateSCLK)) {
  887.           dbg_printf(("Error - subtitle too longn"));
  888.           }
  889.             // check if the end time of new subtitle has passed too
  890.             if (g_dwNextSubtitleUpdateSCLK < dwCurrentTime) {
  891.              subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK);
  892.             }
  893.             // tell the UI to display the string
  894.             else {
  895.                SET_AUX_SUBTITLE_BUFFER_LOCKED(TRUE);
  896.              ie_send(IE_UI_START_DISPLAY_AUX_SUBTITLE);
  897.                SET_AUX_SUBTITLE_START_DISPLAY(FALSE);
  898.             }
  899. }
  900.          else {
  901.           subtitleStorageSkipSubtitle(&g_dwNextSubtitleUpdateSCLK);
  902.          }
  903.       }
  904.       else {
  905.        // the subtitle was displayed, and now it's the time to stop displaying
  906.          subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK);
  907.          // avoid sending the stop event when the next subtitle should be
  908.          // displayed immidiately
  909.          if ( dwCurrentTime < g_dwNextSubtitleUpdateSCLK )
  910.           ie_send(IE_UI_STOP_DISPLAY_AUX_SUBTITLE);
  911.          SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  912.       }
  913.    }
  914. }
  915. /////////////////////////////////////////////////////////////////////////////////////////////
  916. // Function Name  : unlockAuxSubtitlesStringBuffer
  917. // Purpose  : unlock the string buffer
  918. // Return type : void
  919. // Description : After the UI receives an event from the core task to display subtitles
  920. //                  and processes the text in the subtitle string buffer, it calls this function
  921. //   to designate that it no longer needs the data in the subtitles string buffer.
  922. //   The core task can fill the buffer only when it's unlocked, and it locks
  923. //   it before sending display subtitles event to the UI task.
  924. /////////////////////////////////////////////////////////////////////////////////////////////
  925. void unlockAuxSubtitlesStringBuffer(void)
  926. {
  927. SET_AUX_SUBTITLE_BUFFER_LOCKED(FALSE);
  928. }
  929. /////////////////////////////////////////////////////////////////////////////////////////////
  930. // Function Name  : updateSubtitlesIndex
  931. // Purpose  : add a new entry to the subtitles index
  932. // Input parameters: dwAddress   - offest in bytes of the new entry, from the start of
  933. //   the subtitles storage memory.
  934. // dwStartSCLK - start SCLK count for the new subtitle.
  935. // Return type : void
  936. // Description : This function is called for each new subtitles entry. It checks if
  937. //   the entry should be indexed, and stores its time and address if it
  938. //   should. In any given time, there's a uniform interval (in subtitle
  939. //   entries) between each index entry. When the index is full, half of
  940. //                  the entries are discarded and the interval is multiplied by 2.
  941. /////////////////////////////////////////////////////////////////////////////////////////////
  942. #ifdef  AUX_SUBTITLES_INDEX
  943. void updateSubtitlesIndex(DWORD dwAddress, DWORD dwStartSCLK)
  944. {
  945.    int i;
  946.    g_pSubtitleIndex->wSubtitlesModulu ++;
  947.    if ( g_pSubtitleIndex->wSubtitlesModulu == g_pSubtitleIndex->wInterval ) {
  948.     if ( g_pSubtitleIndex->bIndexPosition == SUBTITLE_INDEX_ENTRIES ) {
  949.        for ( i=1 ; i< SUBTITLE_INDEX_ENTRIES ; i +=2 ) {
  950.           g_pSubtitleIndex->entry[i>>1].dwAddress = g_pSubtitleIndex->entry[i].dwAddress;
  951.           g_pSubtitleIndex->entry[i>>1].dwStartTime = g_pSubtitleIndex->entry[i].dwStartTime;
  952.          }
  953. g_pSubtitleIndex->wInterval = g_pSubtitleIndex->wInterval << 1;
  954.          g_pSubtitleIndex->bIndexPosition = SUBTITLE_INDEX_ENTRIES / 2;
  955.       }
  956.     g_pSubtitleIndex->entry[g_pSubtitleIndex->bIndexPosition].dwAddress = dwAddress;
  957.       g_pSubtitleIndex->entry[g_pSubtitleIndex->bIndexPosition++].dwStartTime = dwStartSCLK;
  958.       g_pSubtitleIndex->wSubtitlesModulu = 0;
  959.    }
  960. }
  961. #endif // AUX_SUBTITLES_INDEX
  962. /////////////////////////////////////////////////////////////////////////////////////////////
  963. // Function Name  : subtitleGoToTime
  964. // Purpose  : Jump to a new time in the subtitle storage
  965. // Input parameters: dwCurrentTime - the new time
  966. // Return type :  void
  967. // Description :  After FF/FB/Goto, this function is used to set the next subtitle to be
  968. //                   the 1 right before the new time.
  969. /////////////////////////////////////////////////////////////////////////////////////////////
  970. void subtitleGoToTime(DWORD dwCurrentTime)
  971. {
  972. #ifdef DEBUG_AUX_SUBTITLES
  973. DWORD dwStart;
  974.    DWORD dwEnd;
  975.    dwStart=gen_timer();
  976. #endif
  977. // <<< Robin_0318_2005, need re-allocate the memory 
  978. _allocateStorageInterface();
  979. // >>> Robin_0318_2005
  980.     // WARNING: disable next 4 lines before uncommenting the next section
  981.    g_pSubtitleStorage->dwCurrentStorageOffset = 0;
  982.  g_pSubtitleStorage->wBufferPos=0;
  983.     subtitleStorageFillBuffer();
  984.     subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK);
  985.     /* Disabled until time can be determined before playback starts.
  986.     // look for the first indexed entry with later time
  987.     for (i=0 ; g_pSubtitleIndex->entry[i].dwStartTime<dwCurrentTime && i < g_pSubtitleIndex->bIndexPosition ; i++)
  988.     {
  989.     }
  990.     // start search from the previous indexed entry, or from the beginning of
  991.     // subtitle memory if the 1st indexed entry is too late
  992.     dwPreviousAddress = i > 1 ? g_pSubtitleIndex->entry[i-1].dwAddress : 0 ;
  993.     g_pSubtitleStorage->dwCurrentStorageOffset = dwPreviousAddress ;
  994.  g_pSubtitleStorage->wBufferPos=0;
  995.     subtitleStorageFillBuffer();
  996.     // The time was indexed, so this function call only comes to advances
  997.     // the reading pointer.
  998.     subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK);
  999.     // search subtitle memory sequentially for the last subtitle before
  1000.     // the current time
  1001.     while (1)
  1002.     {
  1003.      if ( g_dwNextSubtitleUpdateSCLK >= dwCurrentTime )
  1004.      break;
  1005.       dwPreviousAddress = g_pSubtitleStorage->dwCurrentStorageOffset +
  1006.           g_pSubtitleStorage->wBufferPos - STORAGE_INTERFACE_BUFFER_SIZE - 4;
  1007.      subtitleStorageSkipSubtitle(&g_dwNextSubtitleUpdateSCLK);
  1008.     }
  1009.     g_pSubtitleStorage->dwCurrentStorageOffset = dwPreviousAddress ;
  1010.  g_pSubtitleStorage->wBufferPos=0;
  1011.     subtitleStorageFillBuffer();
  1012.     subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK); */
  1013.     SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  1014. #ifdef DEBUG_AUX_SUBTITLES
  1015.    dwEnd=gen_timer();
  1016.    dbg_printf(("Subtitles seek time: %lun",dwEnd-dwStart));
  1017. #endif
  1018. }
  1019. /////////////////////////////////////////////////////////////////////////////////////////////
  1020. // Function Name  : setSubtitlesPlayMode
  1021. // Purpose  : Sets the play mode for subtitles - whether the core task should
  1022. //                   check for new subtitles or not.
  1023. // Input parameters: mode - whether play mode is on
  1024. // Return type :  void
  1025. // Description :  Before using FF/FB/Goto, play mode should be set to FALSE so that the
  1026. // core task won't try to search for subtitles. After FF/FB/Goto is done
  1027. // and subtitleGoToTime is called, play more should be set to TRUE.
  1028. /////////////////////////////////////////////////////////////////////////////////////////////
  1029. void setSubtitlesPlayMode(BOOL mode)
  1030. {
  1031.    // transition from scanning to normal playback
  1032.    /*
  1033.    if (!IS_AUX_SUBTITLE_PLAY_MODE && mode == TRUE) {
  1034.     //SET_AUX_SUBTITLE_PERFORM_SEEK(TRUE);
  1035.    } */
  1036.    SET_AUX_SUBTITLE_PLAY_MODE(mode);
  1037.    dbg_printf(("Subtitles mode - %dn",mode));
  1038. }
  1039. /////////////////////////////////////////////////////////////////////////////////////////////
  1040. // Function Name  : stopDisplayAuxSubtitles
  1041. // Purpose  : notify the UI to stop displaying the current subtitle
  1042. // Return type :  void
  1043. // Description :
  1044. /////////////////////////////////////////////////////////////////////////////////////////////
  1045. void stopDisplayAuxSubtitles(void)
  1046. {
  1047. ie_send(IE_UI_STOP_DISPLAY_AUX_SUBTITLE);
  1048. //Stivenz_1115_04: Memory optimization: Move g_SubtitleStorage and g_SubtitleIndex to heap.
  1049. _freeStorageInterfaceAndIndex();
  1050. }
  1051. BOOL areAuxSubtitlePresent(void)
  1052. {
  1053. return IS_AUX_SUBTITLE_AVAILABE;
  1054. }
  1055. // <<< Robin_0907_2004
  1056. BOOL areAuxSubtitleExist(void)
  1057. {
  1058. return IS_AUX_SUBTITLE_EXIST;
  1059. }
  1060. // >>> Robin_0907_2004
  1061. /*
  1062. void switchBytesInWString(LPSTR str)
  1063. {
  1064. WCHAR tmp;
  1065. WCHAR *p = (WCHAR *)str;
  1066.    while (*p != NULL )
  1067.    {
  1068.     tmp = *p;
  1069.       *p= (((tmp&0xff)<<8) | ((tmp&0xff00)>>8));
  1070.       p++;
  1071.    }
  1072. }
  1073. */
  1074. // <<< Stivenz_1115_2004: Move g_SubtitleStorage to heap to save memory.
  1075. ////////////////////////////////////////////////////////////////////////////////////////////
  1076. // Function Name  : _allocateStorageInterface
  1077. // Purpose  : malloc memory for auxiliary subtitle storage interface.
  1078. // Return type :  TRUE if success, otherwise FASLE
  1079. // Description :this function is only for memory optimization.
  1080. /////////////////////////////////////////////////////////////////////////////////////////////
  1081. static BOOL _allocateStorageInterface(void)
  1082. {
  1083. if( NULL == g_pSubtitleStorage)
  1084. {
  1085. //dbg_printf(("initAuxSubtitles() malloc for g_pSubtitleStorage.n"));
  1086. g_pSubtitleStorage = malloc(sizeof(SubtitleStorageInterface));
  1087. if( NULL == g_pSubtitleStorage)
  1088. {
  1089. tr_printf(("FATAL: initAuxSubtitles() Failed [1]: Malloc failed. Low system resource.n"));
  1090. return FALSE;
  1091. }
  1092. }
  1093. return TRUE;
  1094. }
  1095. #ifdef AUX_SUBTITLES_INDEX
  1096. ////////////////////////////////////////////////////////////////////////////////////////////
  1097. // Function Name  : _allocateStorageIndex
  1098. // Purpose  : malloc memory for auxiliary subtitle storage index.
  1099. // Return type :  TRUE if success, otherwise FASLE
  1100. // Description :this function is only for memory optimization.
  1101. /////////////////////////////////////////////////////////////////////////////////////////////
  1102. static BOOL _allocateStorageIndex(void)
  1103. {
  1104. if(NULL == g_pSubtitleIndex)
  1105. {
  1106. //dbg_printf(("initAuxSubtitles() malloc for g_pSubtitleIndex.n"));
  1107. g_pSubtitleIndex = malloc(sizeof(SubtitleStorageIndex));
  1108. if( NULL == g_pSubtitleIndex)
  1109. {
  1110. tr_printf(("FATAL: initAuxSubtitles() Failed [2]: Malloc failed. Low system resource.n"));
  1111. return FALSE;
  1112. }
  1113. }
  1114. return TRUE;
  1115. }
  1116. #endif 
  1117. ////////////////////////////////////////////////////////////////////////////////////////////
  1118. // Function Name  : _FreeStorageInterfaceAndIndex
  1119. // Purpose  : free memory of auxiliary subtitle storage interface or index .
  1120. // Return type :  TRUE if success, otherwise FASLE
  1121. // Description :this function is only for memory optimization.
  1122. /////////////////////////////////////////////////////////////////////////////////////////////
  1123. #ifdef V882_FLASH_CARD
  1124. BOOL _freeStorageInterfaceAndIndex(void)
  1125. #else
  1126. static BOOL _freeStorageInterfaceAndIndex(void)
  1127. #endif
  1128. {
  1129. SAFELY_FREE_PTR(g_pSubtitleStorage);
  1130. #ifdef AUX_SUBTITLES_INDEX
  1131. SAFELY_FREE_PTR(g_pSubtitleIndex);
  1132. #endif // AUX_SUBTITLES_INDEX
  1133. return TRUE;
  1134. }
  1135. // Stivenz_1115_2004 >>>
  1136. #ifdef IS_MP4_CAPABLE
  1137. static void _mp4SubtitleReadDRAM(UINT32 ulAddress, UINT16* pBuffer, UINT32 ulLength )
  1138. {
  1139. UINT32 ulWriteLengthFirst;
  1140. UINT32 ulWriteLngthSecond;
  1141. UINT32 ulBufferStartAddr, ulBufferEndAddr;
  1142. ulBufferStartAddr = _mpeg4InternalSubtitleBufferStartAddr * 512UL;
  1143. ulBufferEndAddr = (_mpeg4InternalSubtitleBufferStartAddr + SPB_SIZE_AVI) * 512UL;
  1144.     while(ulAddress >= ulBufferEndAddr)
  1145.    {
  1146. ulAddress -= (ulBufferEndAddr - ulBufferStartAddr);
  1147.    }
  1148.    ulWriteLengthFirst = min(ulLength, ulBufferEndAddr -ulAddress);
  1149.    ulWriteLngthSecond = ulLength - ulWriteLengthFirst;
  1150.    wai_sem(SEM_DRAM_ID);
  1151.    I49_ReadDRAMDataNSW(ulAddress, (UINT16*)pBuffer, ulWriteLengthFirst);
  1152.    
  1153.    if ( ulWriteLngthSecond != 0UL)
  1154.    {
  1155.       I49_ReadDRAMDataNSW(ulBufferStartAddr, (UINT16*)(pBuffer + ulWriteLengthFirst ), ulWriteLngthSecond );
  1156.    }
  1157.    sig_sem(SEM_DRAM_ID);
  1158.    return;
  1159. }
  1160. static void _mp4SubtitleLoadTime(UINT32 *ulTime)
  1161. {
  1162. _mp4SubtitleReadDRAM( _dwMP4SubtitleReadDRAMAddr, (UINT16*)(ulTime), 2 );
  1163. _dwMP4SubtitleReadDRAMAddr += 2;
  1164. }
  1165. static BOOL _mp4SubtitleLoadSample(void)
  1166. {
  1167. UINT32 ulSampleSize;
  1168. UINT32 ulSampleSizeInWord;
  1169. BYTE pBuffer[32];
  1170. UINT16 uiSampleCount;
  1171. UINT16 uiSampleOffset;
  1172. WORD pUnicodeBuffer[32];
  1173. WORD wLastUnicode = 0;
  1174. UINT16 uiUnicodeOffset = 0;
  1175. _mp4SubtitleReadDRAM( _dwMP4SubtitleReadDRAMAddr, (UINT16*)(&ulSampleSize), 2 );
  1176. _dwMP4SubtitleReadDRAMAddr += 2;
  1177. ulSampleSizeInWord = (ulSampleSize+1)/2;
  1178. uiSampleCount = min(ulSampleSize,SUBTITLE_STRING_SC_SZ_B); 
  1179. uiSampleOffset = 0;
  1180. while(uiSampleCount > 0)
  1181. {
  1182. UINT16 uiBufferSize;
  1183. UINT16 uiUnicodeBufferSize;
  1184. uiBufferSize = min(uiSampleCount, 32);
  1185.  
  1186. _mp4SubtitleReadDRAM( (_dwMP4SubtitleReadDRAMAddr + (uiSampleOffset/2)), (UINT16*)pBuffer, ((uiBufferSize+1)/2) );
  1187. uiUnicodeBufferSize = 0;
  1188. UTF8ToUnicode(pBuffer, pUnicodeBuffer, uiBufferSize, &wLastUnicode, &uiUnicodeBufferSize);
  1189.        sc_SetBytes(SC_AUX_SUBTITLES_STRINGS_ADDR, 2*uiUnicodeOffset, 2*uiUnicodeBufferSize, (BYTE*)(&pUnicodeBuffer[0]) );
  1190.         uiSampleOffset += uiBufferSize;
  1191. uiSampleCount -= uiBufferSize;             
  1192. uiUnicodeOffset += uiUnicodeBufferSize;
  1193. }
  1194. _dwMP4SubtitleReadDRAMAddr += ulSampleSizeInWord;
  1195. return (ulSampleSize < SUBTITLE_STRING_SC_SZ_B);
  1196. }
  1197. static void _mp4SubtitleSkipSubtitle(UINT32 *ulTime)
  1198. {
  1199. UINT32 ulSampleSize;
  1200. UINT32 ulSampleSizeInWord;
  1201. _mp4SubtitleReadDRAM( _dwMP4SubtitleReadDRAMAddr, (UINT16*)(&ulSampleSize), 2 );
  1202. _dwMP4SubtitleReadDRAMAddr += 2;
  1203. ulSampleSizeInWord = (ulSampleSize+1)/2;
  1204. _dwMP4SubtitleReadDRAMAddr += ulSampleSizeInWord;
  1205. _dwMP4SubtitleReadDRAMAddr += 2; // skip end time
  1206. _mp4SubtitleReadDRAM( _dwMP4SubtitleReadDRAMAddr, (UINT16*)(ulTime), 2 );
  1207. _dwMP4SubtitleReadDRAMAddr += 2;
  1208. }
  1209. void mp4InitSubtitles(void)
  1210. {
  1211. g_dwNextSubtitleUpdateSCLK = LAST_SUBTITLE_MARKER;
  1212. SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  1213.     SET_AUX_SUBTITLE_BUFFER_LOCKED(FALSE);
  1214.  //   SET_AUX_SUBTITLE_AVAILABE(TRUE);
  1215.  //   setSubtitlesPlayMode(TRUE);
  1216. }
  1217. void mp4CheckAndHandleSubtitle(DWORD dwCurrentTime)
  1218. {
  1219. if (_dwMP4SubtitleReadDRAMAddr == _dwMP4SubtitleWriteDRAMAddr) // no data
  1220. {
  1221. if (IS_AUX_SUBTITLE_START_DISPLAY)
  1222. return;
  1223.    if ( dwCurrentTime >= g_dwNextSubtitleUpdateSCLK )
  1224.    {
  1225. ie_send(IE_UI_STOP_DISPLAY_AUX_SUBTITLE);
  1226. g_dwNextSubtitleUpdateSCLK = LAST_SUBTITLE_MARKER;
  1227.    SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  1228.    }
  1229. return;
  1230. }
  1231. if (g_dwNextSubtitleUpdateSCLK == LAST_SUBTITLE_MARKER) // first time
  1232. _mp4SubtitleLoadTime(&g_dwNextSubtitleUpdateSCLK);
  1233. while (dwCurrentTime >= g_dwNextSubtitleUpdateSCLK)
  1234. {
  1235. if (IS_AUX_SUBTITLE_START_DISPLAY)
  1236. {
  1237. if (FALSE == IS_AUX_SUBTITLE_BUFFER_LOCKED)
  1238. {
  1239. if ( FALSE == _mp4SubtitleLoadSample())
  1240. {
  1241. dbg_printf(("Error - subtitle too longn"));
  1242. }
  1243. _mp4SubtitleLoadTime(&g_dwNextSubtitleUpdateSCLK);
  1244. if (g_dwNextSubtitleUpdateSCLK < dwCurrentTime) {
  1245. _mp4SubtitleLoadTime(&g_dwNextSubtitleUpdateSCLK);
  1246. }
  1247. else
  1248. {
  1249. SET_AUX_SUBTITLE_BUFFER_LOCKED(TRUE);
  1250.   ie_send(IE_UI_START_DISPLAY_AUX_SUBTITLE);
  1251. SET_AUX_SUBTITLE_START_DISPLAY(FALSE);
  1252. }
  1253. }
  1254. else
  1255. {
  1256. _mp4SubtitleSkipSubtitle(&g_dwNextSubtitleUpdateSCLK);
  1257. }
  1258. }
  1259. else
  1260. {
  1261.    _mp4SubtitleLoadTime(&g_dwNextSubtitleUpdateSCLK);
  1262.    if ( dwCurrentTime < g_dwNextSubtitleUpdateSCLK )
  1263.    {
  1264.   ie_send(IE_UI_STOP_DISPLAY_AUX_SUBTITLE);
  1265. }
  1266.    SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  1267. }
  1268. }
  1269. }
  1270. #endif
  1271. // Robin_0117_2005, support AVI internal text subtitle
  1272. #ifdef IS_AVI_CAPABLE
  1273. static BOOL _aviProcessInternalSubtitleText(DWORD dwStartLBA, DWORD dwFileSize)
  1274. {
  1275. BOOL bAuxSubtitle = FALSE;
  1276. SubtitleParsingFuncPtr pfParseSubtitles;
  1277. UINT16 uiCount;
  1278.     SET_AUX_SUBTITLE_AVAILABE(FALSE);
  1279.     g_dwNextSubtitleUpdateSCLK = LAST_SUBTITLE_MARKER;
  1280. for (uiCount=0;uiCount<SF_NUMBER_OF_FORMATS;uiCount++)
  1281. {
  1282. if ( NULL != availableSubtitleFormats[uiCount].pfProbe)
  1283. {
  1284. if (TRUE == availableSubtitleFormats[uiCount].pfProbe(dwStartLBA, dwFileSize))
  1285. {
  1286. pfParseSubtitles=availableSubtitleFormats[uiCount].pfParse;
  1287. bAuxSubtitle = TRUE;
  1288. break;
  1289. }
  1290. }
  1291. }
  1292. if (bAuxSubtitle == FALSE)
  1293. {
  1294. tr_printf(("_aviProcessInternalSubtitleText - Couldn't probe subtitles filen"));
  1295. return FALSE;
  1296. }
  1297. // _mpeg4ExternalSubtitleAddr = _dwMPEG4ProcessingEndAddr;
  1298.    // if so, parse it and store its content.
  1299. if ( FALSE == pfParseSubtitles(dwStartLBA,dwFileSize,_mpeg4VideoScale,_mpeg4VideoRate)) {
  1300. tr_printf(("_aviProcessInternalSubtitleText - Couldn't parse subtitles filen"));
  1301. return FALSE;
  1302. }
  1303. _dwMPEG4ProcessingEndAddr = (CALC_SUBTITLE_ADDRESS( _mpeg4ExternalSubtitleAddr, g_pSubtitleStorage->dwCurrentStorageOffset) >>9) <<9;
  1304. _dwMPEG4ProcessingEndAddr = (_dwMPEG4ProcessingEndAddr>>9)<<9;
  1305.  
  1306. dbg_printf(("Start Address of Current External Subtitle : 0x%lxn",_dwMPEG4ProcessingEndAddr));
  1307. subtitleStorageInitReading();
  1308.     subtitleStorageGetStartTime(&g_dwNextSubtitleUpdateSCLK);
  1309.     SET_AUX_SUBTITLE_START_DISPLAY(TRUE);
  1310.     SET_AUX_SUBTITLE_BUFFER_LOCKED(FALSE);
  1311.     SET_AUX_SUBTITLE_AVAILABE(TRUE);
  1312.     setSubtitlesPlayMode(TRUE);
  1313. return TRUE;
  1314. }
  1315. ////////////////////////////////////////////////////////////////////////////
  1316. // Function name : _aviParseInternalSubtileText
  1317. // Purpose : Parse the internal subtitle (Text)
  1318. // Input Parameters : 
  1319. // Return type : 
  1320. // Description : 
  1321. ////////////////////////////////////////////////////////////////////////////
  1322. BOOL aviParseInternalSubtileText()
  1323. {
  1324. DWORD  dwTextStartLBA;
  1325. DWORD  dwTextStartOffset;
  1326. CHAR  ucChunkID[4]; 
  1327. UINT16 uiStreamNumber;
  1328. DWORD dwNameSize;
  1329. DWORD dwSize;
  1330. g_dwSubtitleExtraOffset = 0;
  1331. dwTextStartLBA = _dwMPEG4ClipStartLBA + ( (_wMPEG4ClipStartOffset + _mpeg4SubtitleOffsetInAvi - FOURCC_FIELD_LENGTH) >> 11);
  1332. dwTextStartOffset = (WORD)((_wMPEG4ClipStartOffset + _mpeg4SubtitleOffsetInAvi -FOURCC_FIELD_LENGTH) % LOGICAL_BLOCK_SIZE);
  1333. if (!AuxCache_GetBytes(dwTextStartLBA, dwTextStartOffset, 4, ucChunkID))
  1334. {
  1335. dbg_printf(("_aviParseInternalSubtileText(): AuxCache_GetBytes Failedn"));
  1336. return FALSE;
  1337. }
  1338. uiStreamNumber = (ucChunkID[0] - '0')*10 + ucChunkID[1] - '0';
  1339. if (uiStreamNumber == _mpeg4SubtitleStreamID && 't' == ucChunkID[2])
  1340. {
  1341. dwTextStartOffset += 4; // **tx
  1342. dwTextStartOffset += 4; // chunk size
  1343. dwTextStartOffset += 4; // char[4]; // ’GAB2’
  1344. dwTextStartOffset += 1; // BYTE 0x00;
  1345. dwTextStartOffset += 2; // WORD 0x02; // unicode
  1346. if (!AuxCache_GetBytes(dwTextStartLBA, dwTextStartOffset, 4, &dwNameSize))
  1347. {
  1348. dbg_printf(("_aviParseInternalSubtileText(): AuxCache_GetBytes Failedn"));
  1349. return FALSE;
  1350. }
  1351. dwTextStartOffset += 4; // DWORD dwSize_name; // length of stream name in bytes
  1352. dwTextStartOffset += dwNameSize; // char name[dwSize_name]; // zero-terminated subtitle stream name encoded in UTF-16
  1353. dwTextStartOffset +=2; // WORD 0x04;
  1354. if (!AuxCache_GetBytes(dwTextStartLBA, dwTextStartOffset, 4, &dwSize))
  1355. {
  1356. dbg_printf(("_aviParseInternalSubtileText(): AuxCache_GetBytes Failedn"));
  1357. return FALSE;
  1358. }
  1359. dwTextStartOffset += 4; // DWORD dwSize; // size of SRT/SSA text file
  1360. // char data[dwSize]; // entire SRT/SSA file
  1361. dwTextStartLBA += (dwTextStartOffset
  1362. >>11);
  1363. dwTextStartOffset = dwTextStartOffset % LOGICAL_BLOCK_SIZE;
  1364. g_dwSubtitleExtraOffset = dwTextStartOffset;
  1365. return(_aviProcessInternalSubtitleText(dwTextStartLBA, dwSize));
  1366. }
  1367. else
  1368. {
  1369. return FALSE;
  1370. }
  1371. }
  1372. #endif
  1373. #endif //  USE_AUX_SUBTITLES