CCDecoder.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:9k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /* 
  2.  * Copyright (C) 2003-2005 Gabest
  3.  * http://www.gabest.org
  4.  *
  5.  *  This Program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2, or (at your option)
  8.  *  any later version.
  9.  *   
  10.  *  This Program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13.  *  GNU General Public License for more details.
  14.  *   
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with GNU Make; see the file COPYING.  If not, write to
  17.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  18.  *  http://www.gnu.org/copyleft/gpl.html
  19.  *
  20.  */
  21. #include "StdAfx.h"
  22. #include "ccdecoder.h"
  23. CCDecoder::CCDecoder(CString fn, CString rawfn) : m_fn(fn), m_rawfn(rawfn)
  24. {
  25. m_sts.CreateDefaultStyle(ANSI_CHARSET);
  26. m_time = 0;
  27. m_fEndOfCaption = false;
  28. memset(m_buff, 0, sizeof(m_buff));
  29. memset(m_disp, 0, sizeof(m_disp));
  30. m_cursor = CPoint(0, 0);
  31. if(!m_rawfn.IsEmpty()) 
  32. _tremove(m_rawfn);
  33. }
  34. CCDecoder::~CCDecoder()
  35. {
  36. if(m_sts.GetSize() > 0 && !m_fn.IsEmpty()) 
  37. {
  38. m_sts.Sort();
  39. m_sts.SaveAs(m_fn, EXTSRT, -1, CTextFile::ASCII);
  40. m_sts.SaveAs(m_fn.Left(m_fn.ReverseFind('.')+1) + _T("utf8.srt"), EXTSRT, -1, CTextFile::UTF8);
  41. m_sts.SaveAs(m_fn.Left(m_fn.ReverseFind('.')+1) + _T("utf16le.srt"), EXTSRT, -1, CTextFile::LE16);
  42. m_sts.SaveAs(m_fn.Left(m_fn.ReverseFind('.')+1) + _T("utf16be.srt"), EXTSRT, -1, CTextFile::BE16);
  43. }
  44. }
  45. void CCDecoder::MoveCursor(int x, int y)
  46. {
  47. m_cursor = CPoint(x, y);
  48. if(m_cursor.x < 0) m_cursor.x = 0;
  49. if(m_cursor.y < 0) m_cursor.y = 0;
  50. if(m_cursor.x >= 32) m_cursor.x = 0, m_cursor.y++;
  51. if(m_cursor.y >= 16) m_cursor.y = 0;
  52. }
  53. void CCDecoder::OffsetCursor(int x, int y)
  54. {
  55. MoveCursor(m_cursor.x + x, m_cursor.y + y);
  56. }
  57. void CCDecoder::PutChar(WCHAR c)
  58. {
  59. m_buff[m_cursor.y][m_cursor.x] = c;
  60. OffsetCursor(1, 0);
  61. }
  62. void CCDecoder::SaveDisp(__int64 time)
  63. {
  64. CStringW str;
  65. for(int row = 0; row < 16; row++)
  66. {
  67. bool fNonEmptyRow = false;
  68. for(int col = 0; col < 32; col++)
  69. {
  70. if(m_disp[row][col]) 
  71. {
  72. CStringW str2(&m_disp[row][col]);
  73. if(fNonEmptyRow) str += ' ';
  74. str += str2;
  75. col += str2.GetLength();
  76. fNonEmptyRow = true;
  77. }
  78. }
  79. if(fNonEmptyRow) str += 'n';
  80. }
  81. if(str.IsEmpty()) return;
  82. m_sts.Add(str, true, (int)m_time, (int)time);
  83. }
  84. void CCDecoder::DecodeCC(BYTE* buff, int len, __int64 time)
  85. {
  86. if(!m_rawfn.IsEmpty())
  87. {
  88. if(FILE* f = _tfopen(m_rawfn, _T("at")))
  89. {
  90. _ftprintf(f, _T("%02d:%02d:%02d.%03dn"), 
  91. (int)(time/1000/60/60), 
  92. (int)((time/1000/60)%60), 
  93. (int)((time/1000)%60), 
  94. (int)(time%1000));
  95. for(int i = 0; i < len; i++)
  96. {
  97. _ftprintf(f, _T("%02x"), buff[i]);
  98. if(i < len-1) _ftprintf(f, _T(" "));
  99. if(i > 0 && (i&15)==15) _ftprintf(f, _T("n"));
  100. }
  101. if(len > 0) _ftprintf(f, _T("nn"));
  102. fclose(f);
  103. }
  104. }
  105. for(int i = 0; i < len; i++)
  106. {
  107. BYTE c = buff[i]&0x7f;
  108. if(c >= 0x20)
  109. {
  110. static WCHAR charmap[0x60] = 
  111. {
  112. ' ','!','"','#','$','%','&',''','(',')',' ','+',',','-','.','/',
  113. '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>',' ',
  114. '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
  115. 'P','Q','R','S','T','U','V','W','X','Y','Z','[',' ',']',' ',' ',
  116. ' ','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
  117. 'p','q','r','s','t','u','v','w','x','y','z',' ',' ','N','n',' '
  118. };
  119. PutChar(charmap[c - 0x20]);
  120. }
  121. else if(buff[i] != 0x80 && i < len-1)
  122. {
  123. // codes and special characters are supposed to be doubled
  124. if(i < len-3 && buff[i] == buff[i+2] && buff[i+1] == buff[i+3])
  125.   i += 2;
  126. c = buff[i+1]&0x7f;
  127. if(buff[i] == 0x91 && c >= 0x20 && c < 0x30) // formating
  128. {
  129. // TODO
  130. }
  131. else if(buff[i] == 0x91 && c == 0x39) // transparent space
  132. {
  133.   OffsetCursor(1, 0);
  134. }
  135. else if(buff[i] == 0x91 && c >= 0x30 && c < 0x40) // special characters
  136. {
  137. static WCHAR charmap[0x10] =
  138. {
  139. 0x00ae, // (r)egistered
  140. 0x00b0, // degree
  141. 0x00bd, // 1/2
  142. 0x00bf, // inverted question mark
  143. 0x2122, // trade mark
  144. 0x00a2, // cent
  145. 0x00a3, // pound
  146. 0x266a, // music
  147. 0x00e0, // a`
  148. 0x00ff, // transparent space, handled above
  149. 0x00e8, // e`
  150. 0x00e2, // a^
  151. 0x00ea, // e^
  152. 0x00ee, // i^
  153. 0x00f4, // o^
  154. 0x00fb, // u^
  155. };
  156. PutChar(charmap[c - 0x30]);
  157. }
  158. else if(buff[i] == 0x92 && c >= 0x20 && c < 0x40) // extended characters
  159. {
  160. static WCHAR charmap[0x20] =
  161. {
  162. 0x00c0, // A'
  163. 0x00c9, // E'
  164. 0x00d3, // O'
  165. 0x00da, // U'
  166. 0x00dc, // U:
  167. 0x00fc, // u:
  168. 0x2018, // `
  169. 0x00a1, // inverted !
  170. 0x002a, // *
  171. 0x2019, // '
  172. 0x002d, // -
  173. 0x00a9, // (c)opyright
  174. 0x2120, // SM
  175. 0x00b7, // . (dot in the middle)
  176. 0x201c, // inverted "
  177. 0x201d, // "
  178. 0x00c1, // A`
  179. 0x00c2, // A^
  180. 0x00c7, // C,
  181. 0x00c8, // E`
  182. 0x00ca, // E^
  183. 0x00cb, // E:
  184. 0x00eb, // e:
  185. 0x00ce, // I^
  186. 0x00cf, // I:
  187. 0x00ef, // i:
  188. 0x00d4, // O^
  189. 0x00d9, // U`
  190. 0x00f9, // u`
  191. 0x00db, // U^
  192. 0x00ab, // <<
  193. 0x00bb, // >>
  194. };
  195. PutChar(charmap[c - 0x20]);
  196. }
  197. else if(buff[i] == 0x13 && c >= 0x20 && c < 0x40) // more extended characters
  198. {
  199. static WCHAR charmap[0x20] =
  200. {
  201. 0x00c3, // A~
  202. 0x00e3, // a~
  203. 0x00cd, // I'
  204. 0x00cc, // I`
  205. 0x00ec, // i`
  206. 0x00d2, // O`
  207. 0x00f2, // o`
  208. 0x00d5, // O~
  209. 0x00f5, // o~
  210. 0x007b, // {
  211. 0x007d, // }
  212. 0x005c, // /*  */
  213. 0x005e, // ^
  214. 0x005f, // _
  215. 0x00a6, // |
  216. 0x007e, // ~
  217. 0x00c4, // A:
  218. 0x00e4, // a:
  219. 0x00d6, // O:
  220. 0x00f6, // o:
  221. 0x00df, // B (ss in german)
  222. 0x00a5, // Y=
  223. 0x00a4, // ox
  224. 0x007c, // |
  225. 0x00c5, // Ao
  226. 0x00e5, // ao
  227. 0x00d8, // O/
  228. 0x00f8, // o/
  229. 0x250c, // |-
  230. 0x2510, // -|
  231. 0x2514, // |_
  232. 0x2518, // _|
  233. };
  234. PutChar(charmap[c - 0x20]);
  235. }
  236. else if(buff[i] == 0x94 && buff[i+1] == 0xae) // Erase Non-displayed [buffer] Memory
  237. {
  238. memset(m_buff, 0, sizeof(m_buff));
  239. }
  240. else if(buff[i] == 0x94 && buff[i+1] == 0x20) // Resume Caption Loading
  241. {
  242. memset(m_buff, 0, sizeof(m_buff));
  243. }
  244. else if(buff[i] == 0x94 && buff[i+1] == 0x2f) // End Of Caption
  245. {
  246.   if(memcmp(m_disp, m_buff, sizeof(m_disp)) != 0)
  247.   {
  248.   if(m_fEndOfCaption)
  249.   SaveDisp(time + (i/2)*1000/30);
  250.  
  251.   m_fEndOfCaption = true;
  252.   memcpy(m_disp, m_buff, sizeof(m_disp));
  253.   m_time = time + (i/2)*1000/30;
  254.   }
  255. }
  256. else if(buff[i] == 0x94 && buff[i+1] == 0x2c) // Erase Displayed Memory
  257. {
  258. if(m_fEndOfCaption)
  259. {
  260. m_fEndOfCaption = false;
  261.   SaveDisp(time + (i/2)*1000/30);
  262. }
  263. memset(m_disp, 0, sizeof(m_disp));
  264. }
  265. else if(buff[i] == 0x97 && (buff[i+1] == 0xa1 || buff[i+1] == 0xa2 || buff[i+1] == 0x23)) // Tab Over
  266. {
  267. OffsetCursor(buff[i+1]&3, 0);
  268. }
  269. else if(buff[i] == 0x91 || buff[i] == 0x92 || buff[i] == 0x15 || buff[i] == 0x16 
  270. || buff[i] == 0x97 || buff[i] == 0x10 || buff[i] == 0x13 || buff[i] == 0x94) // curpos, color, underline
  271. {
  272. int row = 0;
  273. switch(buff[i])
  274. {
  275. default:
  276. case 0x91: row = 0; break;
  277. case 0x92: row = 2; break;
  278. case 0x15: row = 4; break;
  279. case 0x16: row = 6; break;
  280. case 0x97: row = 8; break;
  281. case 0x10: row = 10; break;
  282. case 0x13: row = 12; break;
  283. case 0x94: row = 14; break;
  284. }
  285. if(buff[i+1]&0x20) row++;
  286. int col = buff[i+1]&0xe;
  287. if(col == 0 || (col > 0 && !(buff[i+1]&0x10))) col = 0;
  288. else col <<= 1;
  289. MoveCursor(col, row);
  290. }
  291. else
  292. {
  293. int iiii = 0;
  294. }
  295. i++;
  296. }
  297. }
  298. }
  299. void CCDecoder::ExtractCC(BYTE* buff, int len, __int64 time)
  300. {
  301. for(int i = 0; i < len-9; i++)
  302. {
  303. if(*(DWORD*)&buff[i] == 0xb2010000 && *(DWORD*)&buff[i+4] == 0xf8014343)
  304. {
  305. i += 8;
  306. int nBytes = buff[i++]&0x3f;
  307. if(nBytes > 0)
  308. {
  309. nBytes = (nBytes+1)&~1;
  310. BYTE* pData1 = new BYTE[nBytes];
  311. BYTE* pData2 = new BYTE[nBytes];
  312. if(pData1 && pData2)
  313. {
  314. int nBytes1 = 0, nBytes2 = 0;
  315. for(int j = 0; j < nBytes && i < 0x800;)
  316. {
  317. if(buff[i++] == 0xff)
  318. {
  319. pData1[nBytes1++] = buff[i++];
  320. pData1[nBytes1++] = buff[i++];
  321. }
  322. else i+=2;
  323. j++;
  324. if(j >= nBytes) break;
  325. if(buff[i++] == 0xff)
  326. {
  327. pData2[nBytes2++] = buff[i++];
  328. pData2[nBytes2++] = buff[i++];
  329. }
  330. else i+=2;
  331. j++;
  332. }
  333. if(nBytes1 > 0)
  334. DecodeCC(pData1, nBytes1, time);
  335. if(nBytes2 > 0)
  336. DecodeCC(pData2, nBytes2, time);
  337. }
  338. if(pData1) delete [] pData1;
  339. if(pData2) delete [] pData2;
  340. }
  341. break;
  342. }
  343. }
  344. }