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

DVD

开发平台:

Others

  1. /**************************************************************
  2.  *  AuxSubtitlesFormats_sami.c
  3.  **************************************************************
  4.  *  Description:
  5.  *  ============
  6.  *  Format specific data and functions for subtitles files.
  7.  **************************************************************/
  8. #include "Config.h" // Global Configuration - do not remove!
  9. #if  defined (USE_AUX_SUBTITLES) && defined(SUPPORT_SAMI_SUBTITLE)
  10. #ifdef _DEBUG
  11. #undef IFTRACE
  12. #ifdef DEBUG_AUX_SUBTITLES
  13. #define IFTRACE if (gTraceNavigator)
  14. #else
  15. #define IFTRACE
  16. #endif // DEBUG_AUX_SUBTITLES
  17. #include "Debugdbgmain.h"
  18. #endif // _DEBUG
  19. #include <string.h>
  20. #include "PlaycoreNav_ClipsreadTextFile.h"
  21. #include "PlaycoreNav_ClipsAuxSubtitlesCommonPrivate.h"
  22. #include "PlaycoreNav_ClipsAuxSubtitles.h"
  23. #include "PlaycoreNav_ClipsAuxSubtitlesFormats_sami.h"
  24. // <<< Robin_0907_2004
  25. //#include "PlaycoreNav_ClipsAVI_private.h"
  26. //#include "PlaycoreNav_Clipsnav_clips.h"
  27. #include "PlaycoreCoremainCoreGDef.h"
  28. #include "PlaycoreScPadScPadAlloc.h"
  29. static void parse_body(void);
  30. static void parse_style(BOOL bClass);
  31. // >>> Robin_0907_2004
  32. static void ParseAttrs(void);
  33. static void parse_class_define(char* lang_id);
  34. static BOOL get_token(int mode);
  35. static TOKEN_TYPE ScanTable(void);
  36. static BOOL next_char( char* p );
  37. #define IsWhite(C)   (c==' ' || c=='t')
  38. #define IsLetter(C)  (((c>='a' && c<='z') || (c>='A' && c<='Z')))
  39. typedef struct{
  40. TOKEN  token;
  41. textFilePtr  tfpFile;
  42. char  current_class[10];
  43. char  prefered_class[10];
  44. ULONG current_time;
  45. }SAMI_MEM;
  46. SAMI_MEM *sami_mem;
  47. const TOKEN_LUT token_lut_array[] = 
  48. {
  49. { PARAGRAPH, "p"  },
  50. { TAG_SYNC, "sync"  },
  51. { START, "start"  },
  52. { CLASS, "class" },
  53. { TAG_BR, "br"  },
  54. { TAG_SAMI, "sami"  },
  55. { TAG_END_SAMI,  "/sami"  },
  56. { TAG_BODY, "body"  },
  57. { TAG_END_BODY,  "/body"  },
  58. { TAG_STYLE, "style"  },
  59. { TAG_END_STYLE,  "/style"  },
  60. { SAMI_ID, "id"     },
  61. { LANG, "lang"  },
  62. { SAMI_FONT,            "font"      },
  63. { SAMI_FONT_COLOR,      "color"     },
  64. { SAMI_FONT_END,        "/font"     },
  65. };
  66. BOOL probeSubtitlesFileSami(DWORD dwSubtitlesFileAddress, DWORD dwSubtitlesFileSize)
  67. {
  68. if (NULL == (sami_mem = malloc(sizeof(SAMI_MEM))) )
  69. return FALSE;
  70. sami_mem->tfpFile=textFileOpen(dwSubtitlesFileAddress,dwSubtitlesFileSize);
  71. if ( NULL == sami_mem->tfpFile )
  72. {
  73. free(sami_mem);
  74. return FALSE;
  75. }
  76. if(FALSE == textFileIsCurrentChar(sami_mem->tfpFile, '<') ||
  77. FALSE == textFileIsCurrentChar(sami_mem->tfpFile, 'S') ||
  78. FALSE == textFileIsCurrentChar(sami_mem->tfpFile, 'A') ||
  79. FALSE == textFileIsCurrentChar(sami_mem->tfpFile, 'M') ||
  80. FALSE == textFileIsCurrentChar(sami_mem->tfpFile, 'I') ||
  81. FALSE == textFileIsCurrentChar(sami_mem->tfpFile, '>'))
  82. {
  83. textFileClose(sami_mem->tfpFile);
  84. free(sami_mem);
  85. return FALSE;
  86. }
  87. subtitleStorageInitWriting();
  88. while (1)
  89. {
  90. if (FALSE == get_token(NORMAL) )
  91. break;
  92. switch (sami_mem->token.type)
  93. {
  94. case NULL_TOKEN:
  95. case TAG_END_SAMI:
  96. free(sami_mem);
  97.     textFileClose(sami_mem->tfpFile);
  98. // subtitleStorageMarkLastEntry();
  99. return FALSE;
  100. case TAG_BODY:
  101. case PARAGRAPH:
  102. case TAG_SYNC:
  103. // parse_body();
  104. break;
  105. case TAG_STYLE:
  106. parse_style(TRUE);
  107. free(sami_mem);
  108. textFileClose(sami_mem->tfpFile);
  109. return TRUE;
  110. // break;
  111. default:
  112. break;
  113. }
  114. }
  115. textFileClose(sami_mem->tfpFile);
  116. free(sami_mem);
  117. // subtitleStorageMarkLastEntry();
  118. return FALSE;
  119. }
  120. // >>> Robin_0907_2004
  121. BOOL parseSubtitlesFileSami(DWORD dwSubtitlesFileAddress, DWORD dwSubtitlesFileSize,DWORD dwScale, DWORD dwRate)
  122. {
  123. if (NULL == (sami_mem = malloc(sizeof(SAMI_MEM))) )
  124. return FALSE;
  125.     memset(sami_mem,0,sizeof(SAMI_MEM));
  126. sami_mem->tfpFile=textFileOpen(dwSubtitlesFileAddress,dwSubtitlesFileSize);
  127. if ( NULL == sami_mem->tfpFile )
  128. {
  129. free(sami_mem);
  130. return FALSE;
  131. }
  132. subtitleStorageInitWriting();
  133. while (1)
  134. {
  135. if (FALSE == get_token(NORMAL) )
  136. break;
  137. switch (sami_mem->token.type)
  138. {
  139. case NULL_TOKEN:
  140. case TAG_END_SAMI:
  141. free(sami_mem);
  142.     textFileClose(sami_mem->tfpFile);
  143. subtitleStorageMarkLastEntry();
  144. return TRUE;
  145. case TAG_BODY:
  146. case PARAGRAPH:
  147. case TAG_SYNC:
  148. parse_body();
  149. break;
  150. case TAG_STYLE:
  151. // <<< Robin_0907_2004
  152. parse_style(FALSE);
  153. // >>> Robin_0907_2004
  154. break;
  155. default:
  156. break;
  157. }
  158. }
  159. textFileClose(sami_mem->tfpFile);
  160. free(sami_mem);
  161. subtitleStorageMarkLastEntry();
  162. return TRUE;
  163. }
  164. static void parse_body()
  165. {
  166. long start_time = -1;
  167. int entry_state = 0;          //Ready to write start entry
  168. while (1)
  169. {
  170. if ( FALSE == get_token(IN_BODY) )
  171. return;
  172. switch (sami_mem->token.type)
  173. {
  174. case NULL:
  175. case TAG_END_SAMI:
  176. return;
  177. case PARAGRAPH:
  178. break;
  179. case TAG_BR:
  180. if (0 == strcmp(sami_mem->current_class, sami_mem->prefered_class) ||
  181.                0 == strlen(sami_mem->current_class)  )
  182. subtitleStorageWriteByte(FORMAT_NEW_LINE);
  183. break;
  184. case TAG_END_BODY:
  185. if (entry_state == 1)
  186.        subtitleStorageEndEntry(sami_mem->current_time + 1000);
  187. break;
  188. case TAG_SYNC:
  189. start_time = sami_mem->current_time;
  190. break;
  191. case BLANK_SYNC:
  192. if (entry_state == 1)
  193. {
  194. subtitleStorageEndEntry(sami_mem->current_time);
  195. entry_state = 0;       //Ready to write start entry
  196. }
  197. break;
  198. case CONTENT_STRING:
  199. if (0 == strcmp(sami_mem->current_class, sami_mem->prefered_class) ||
  200.                0 == strlen(sami_mem->current_class)  )
  201. {
  202. int i, len = strlen(sami_mem->token.string);
  203. if (entry_state == 1 && start_time != -1)             //Ready to write end entry
  204. {
  205. subtitleStorageEndEntry(start_time);
  206. entry_state = 0;         //Ready to write start entry
  207. }
  208. if (entry_state == 0)
  209. {
  210. if (start_time == -1)      //Didn't get <SYNC Start=...>
  211. break;
  212. subtitleStorageStartEntry(start_time);
  213. entry_state = 1;         //Ready to write content
  214. }
  215. for (i = 0; i < len; i++)
  216. {
  217. subtitleStorageWriteByte(sami_mem->token.string[i]);
  218. }
  219. start_time = -1;
  220. }
  221. break;
  222. }
  223. }
  224. }
  225. // <<< Robin_0907_2004
  226. static void parse_style(BOOL bClass)
  227. {
  228. // char class_name[10], lang_id[10];
  229. char lang_id[16]; //BT0907: was lang_id[10]
  230. MPEG4SubtitleStreamInfo mpeg4SubtitleStreamInfo;
  231. while (1)
  232. {
  233. get_token(IN_STYLE);
  234. switch (sami_mem->token.type)
  235. {
  236. case NULL_TOKEN:
  237. case TAG_END_STYLE:
  238. return;
  239. case CLASS_DEFINE:
  240. if (TRUE == bClass) // store class_name
  241. {
  242. // <<< Robin_1027_2004
  243. lang_id[0] = '';
  244. parse_class_define(lang_id);
  245. if (lang_id[0] == '')
  246. continue;
  247. // >>> Robin_1027_2004
  248. // Robin_1119_2004, display SAMI subtitle language
  249. memset(&mpeg4SubtitleStreamInfo, 0, sizeof(MPEG4SubtitleStreamInfo));
  250. mpeg4SubtitleStreamInfo.streamID = NO_STREAM;
  251. mpeg4SubtitleStreamInfo.type = SAMI;
  252. strncpy(mpeg4SubtitleStreamInfo.languageCode.language, lang_id, 2);
  253. strcpy(mpeg4SubtitleStreamInfo.className, sami_mem->token.string);
  254. sc_SetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  255. (SI_CLIPS_SUB_AVAILABLE_NUM * SIZE_OF_SUBTITLE_STREAM_INFO),
  256. SIZE_OF_SUBTITLE_STREAM_INFO,
  257. (BYTE*)&mpeg4SubtitleStreamInfo
  258.      );
  259.       
  260. SI_CLIPS_SUB_AVAILABLE_NUM ++;
  261. }
  262. else
  263. {
  264. sc_GetBytes(SC_MPEG4_SUBTITLE_STREAM_INFO_ADDR,
  265. (SI_CLIPS_SUB_CURRENT_DISP_IDX * SIZE_OF_SUBTITLE_STREAM_INFO),
  266. SIZE_OF_SUBTITLE_STREAM_INFO,
  267. (BYTE*)&_mpeg4SubtitleStreamInfo
  268.      );
  269. strcpy(sami_mem->prefered_class, _mpeg4SubtitleStreamInfo.className);      
  270. }
  271. // strcpy(class_name, sami_mem->token.string);
  272. // parse_class_define(lang_id);
  273. //#ifndef USE_AUX_SUBTITLES_KSC5601 //BillTang_0724_04: to support Korean also, but will cause problem if the file contains more than one subtitle
  274. // if (0 == strncmp(lang_id, "en-", 3))        //Only support English
  275. //#endif
  276. // {
  277. // strcpy(sami_mem->prefered_class, sami_mem->token.string);
  278. // }
  279. break;
  280. case STYLE_DEFINE:
  281.  if (FALSE == textFileFindString(sami_mem->tfpFile,"}",0) )
  282.   return;
  283. break;
  284. }
  285. }
  286. }
  287. // >>> Robin_0907_2004
  288. static void ParseAttrs()
  289. {
  290. char c, str[10];
  291. int i;
  292. TOKEN_TYPE attribute;
  293. while(1)
  294. {
  295. if ((attribute = ScanTable()) == NULL_TOKEN)
  296. {
  297. //eat until '>'
  298.  if (FALSE == textFileFindString(sami_mem->tfpFile,">",0) )
  299.   return;
  300.  
  301. break;
  302. }
  303. //eat until '='
  304.  if (FALSE == textFileFindString(sami_mem->tfpFile,"=",0) )
  305.   return;
  306. if (START == attribute && sami_mem->token.type == TAG_SYNC)
  307. {
  308. textFileReadNumber(sami_mem->tfpFile, &sami_mem->current_time);
  309. }
  310. else
  311. {
  312. //Consume whilte space before lang id.
  313. while(1)
  314. {
  315. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c))
  316. return;
  317. if ( !IsWhite(c) )
  318. {
  319. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  320. return;
  321. break;
  322. }
  323. }
  324. //Copy class name
  325. i = 0;
  326. while(1)
  327. {
  328. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c))
  329. return;
  330. if ( IsWhite(c) || c=='>')
  331. {
  332. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  333. return;
  334. break;
  335. }
  336. str[i++] = c;
  337. }
  338. str[i++] = '';
  339. if (CLASS == attribute && sami_mem->token.type == PARAGRAPH)
  340. {
  341. strcpy(sami_mem->current_class, str);
  342. }
  343. }
  344. }
  345. }
  346. static void parse_class_define(char* lang_id)
  347. {
  348. char c;
  349. int i;
  350. TOKEN_TYPE attribute;
  351.  //Consume stream until '}'
  352. // <<< Robin_1027_2004
  353.  while(1)
  354.  {
  355.  if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c) )
  356. return;
  357.  if (IsWhite(c))
  358. continue;
  359.  if ( c == '{')
  360. break;
  361.  else
  362. return;
  363.  }
  364. // if (FALSE == textFileFindString(sami_mem->tfpFile,"{",0) )
  365. // return;
  366. // >>> Robin_1027_2004
  367. while(1)
  368. {
  369. if ((attribute = ScanTable()) == NULL_TOKEN)
  370. {
  371. //eat until '}'
  372. if (FALSE == textFileFindString(sami_mem->tfpFile,"}",0) )
  373. return;
  374. break;
  375. }
  376. if (attribute == LANG)
  377. {
  378. //eat until ':'
  379. if (FALSE == textFileFindString(sami_mem->tfpFile,":",0) )
  380. return;
  381. //Consume whilte space before lang id.
  382. while(1)
  383. {
  384. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c) )
  385. return;
  386. if ( !IsWhite(c) )
  387. {
  388. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  389. return;
  390. break;
  391. }
  392. }
  393. //Copy lang id
  394. i = 0;
  395. while(1)
  396. {
  397. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c) )
  398. return;
  399. if ( IsWhite(c) || c==';')
  400. {
  401. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  402. return;
  403. break;
  404. }
  405. lang_id[i++] = c;
  406. //<<<BT0907: add condition to avoid illegal op
  407. if (i ==15)
  408. break;
  409. //>>>BT0907
  410. }
  411. lang_id[i++] = '';
  412. }
  413. //eat until ';'
  414. if (FALSE == textFileFindString(sami_mem->tfpFile,";",0) )
  415. return;
  416. }
  417. }
  418. static BOOL get_token(int mode)
  419. {
  420. static LEXER_STATE lexer_state = LEX_CONTENT;
  421. int lexer_point;
  422. char c;
  423. sami_mem->token.type = UNKNOWN;
  424. lexer_point = 0;
  425. if ( FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c) )
  426. {
  427. sami_mem->token.type = NULL_TOKEN;
  428. return FALSE;
  429. }
  430. while ( FALSE == textFileEOF(sami_mem->tfpFile) )
  431. {
  432. switch (lexer_state)
  433. {
  434. case LEX_CONTENT:
  435. if (c == '<')
  436. {
  437. lexer_state = LEX_GT;
  438. continue;
  439. }
  440. else if (c=='n' || c=='r')
  441. {
  442. if (lexer_point != 0)
  443. {
  444. sami_mem->token.type = CONTENT_STRING;
  445. sami_mem->token.string[lexer_point] = '';
  446. return TRUE;
  447. }
  448. break;
  449. }
  450. else if (c == ' ')
  451. {
  452. if (mode!=IN_BODY || lexer_point==0)
  453. break;
  454. }
  455. else if (c=='.')
  456. {
  457. if (mode==IN_STYLE && lexer_point==0)
  458. {
  459. while(1)
  460. {
  461. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c) )
  462. return FALSE;
  463. // Robin_0408_2005, for some special token: EN-USCC 
  464. if ( IsWhite(c) )
  465. {
  466. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  467. return FALSE;
  468. break;
  469. }
  470. sami_mem->token.string[lexer_point++] = c;
  471. }
  472. sami_mem->token.type = CLASS_DEFINE;
  473. sami_mem->token.string[lexer_point] = '';
  474. return TRUE;
  475. }
  476. }
  477. else if (c=='P' || c=='#')
  478. {
  479. if (mode==IN_STYLE && lexer_point==0)
  480. {
  481. sami_mem->token.type = STYLE_DEFINE;
  482. return TRUE;
  483. }
  484. }
  485. else if (c == ';' && mode==IN_BODY)
  486. {
  487. if (0 == strncmp(sami_mem->token.string, "&nbsp", 5) )
  488. {
  489. sami_mem->token.type = BLANK_SYNC;
  490. return TRUE;
  491. }
  492. }
  493. if (mode==IN_BODY && lexer_point < (LEN_CONTENT_STR-2))
  494. sami_mem->token.string[lexer_point++] = c;
  495. break;
  496. case LEX_GT:
  497. if ( FALSE == next_char(&c) )
  498. return FALSE;
  499. if (c == '/')
  500. {
  501. lexer_state = LEX_ENDTAG;
  502. if (lexer_point != 0)
  503. {
  504. sami_mem->token.type = CONTENT_STRING;
  505. sami_mem->token.string[lexer_point] = '';
  506. return TRUE;
  507. }
  508. continue;
  509. }
  510. if (IsLetter(c))
  511. {
  512. lexer_state = LEX_STARTTAG;
  513. if (lexer_point != 0)
  514. {
  515. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR)) //Rewind the first character after '<'
  516. return FALSE;
  517. sami_mem->token.type = CONTENT_STRING;
  518. sami_mem->token.string[lexer_point] = '';
  519. return TRUE;
  520. }
  521. continue;
  522. }
  523. lexer_state = LEX_CONTENT;
  524. break;
  525. case LEX_ENDTAG:
  526. sami_mem->token.type = ScanTable();
  527. if (FALSE == textFileFindString(sami_mem->tfpFile,">",0) )
  528. return FALSE;
  529. lexer_state = LEX_CONTENT;
  530. if (sami_mem->token.type != UNKNOWN)
  531. return TRUE;
  532. break;
  533. case LEX_STARTTAG:
  534. sami_mem->token.type = ScanTable();
  535. if ( FALSE == next_char(&c) )
  536. return FALSE;
  537. if (c != '>' && sami_mem->token.type!=UNKNOWN)
  538. ParseAttrs();
  539. else
  540. {
  541. //eat until end of tag '>'
  542. if (FALSE == textFileFindString(sami_mem->tfpFile,">",0) )
  543. return FALSE;
  544. }
  545. lexer_state = LEX_CONTENT;
  546. if (sami_mem->token.type != UNKNOWN)
  547. return TRUE;
  548. break;
  549. }
  550. if ( FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c) )
  551. {
  552. sami_mem->token.type = NULL_TOKEN;
  553. return FALSE;
  554. }
  555. }
  556. return FALSE;
  557. }
  558. static TOKEN_TYPE ScanTable()
  559. {
  560. char c, str[10];
  561. int i = 0;
  562. //Consume whilte space before attribute.
  563. while(1)
  564. {
  565. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c)  )
  566. return NULL_TOKEN;
  567. if ( !IsWhite(c) && (c != 'r') && (c != 'n'))
  568. {
  569. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  570. return NULL_TOKEN;
  571. break;
  572. }
  573. }
  574. while (1)
  575. {
  576. if (FALSE == textFileReadChar(sami_mem->tfpFile, 1, &c))
  577. return NULL_TOKEN;
  578. if (c=='=' || c==':' || c=='>' || c=='{' || c=='}' || IsWhite(c) )
  579. {
  580. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  581. return NULL_TOKEN;
  582. break;
  583. }
  584. str[i++] = c;
  585. }
  586. str[i] = '';
  587. if (i == 0)
  588. return NULL_TOKEN;
  589. strlwr(str);            //Convert to lower case
  590. for (i=0; i<(sizeof(token_lut_array)/sizeof(TOKEN_LUT)); i++)
  591. {
  592. if (0 == strcmp(str, token_lut_array[i].str))
  593. return token_lut_array[i].token;
  594. }
  595. return UNKNOWN;
  596. }
  597. static BOOL next_char( char* p )
  598. {
  599. if ( FALSE == textFileReadChar(sami_mem->tfpFile, 1, p ))
  600. return FALSE;
  601. if (FALSE == textFileSeek(sami_mem->tfpFile,-1,TF_SEEK_CUR))
  602. return FALSE;
  603. return TRUE;
  604. }
  605. #endif //defined (USE_AUX_SUBTITLES) && defined(SUPPORT_SAMI_SUBTITLE)