00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "StdAfx.h"
00023 #include "ccdecoder.h"
00024
00025 CCDecoder::CCDecoder(CString fn, CString rawfn) : m_fn(fn), m_rawfn(rawfn)
00026 {
00027 m_sts.CreateDefaultStyle(ANSI_CHARSET);
00028
00029 m_time = 0;
00030 m_fEndOfCaption = false;
00031 memset(m_buff, 0, sizeof(m_buff));
00032 memset(m_disp, 0, sizeof(m_disp));
00033 m_cursor = CPoint(0, 0);
00034
00035 if(!m_rawfn.IsEmpty())
00036 _tremove(m_rawfn);
00037 }
00038
00039 CCDecoder::~CCDecoder()
00040 {
00041 if(m_sts.GetSize() > 0 && !m_fn.IsEmpty())
00042 {
00043 m_sts.Sort();
00044 m_sts.SaveAs(m_fn, EXTSRT, -1, CTextFile::ASCII);
00045 m_sts.SaveAs(m_fn.Left(m_fn.ReverseFind('.')+1) + _T("utf8.srt"), EXTSRT, -1, CTextFile::UTF8);
00046 m_sts.SaveAs(m_fn.Left(m_fn.ReverseFind('.')+1) + _T("utf16le.srt"), EXTSRT, -1, CTextFile::LE16);
00047 m_sts.SaveAs(m_fn.Left(m_fn.ReverseFind('.')+1) + _T("utf16be.srt"), EXTSRT, -1, CTextFile::BE16);
00048 }
00049 }
00050
00051 void CCDecoder::MoveCursor(int x, int y)
00052 {
00053 m_cursor = CPoint(x, y);
00054 if(m_cursor.x < 0) m_cursor.x = 0;
00055 if(m_cursor.y < 0) m_cursor.y = 0;
00056 if(m_cursor.x >= 32) m_cursor.x = 0, m_cursor.y++;
00057 if(m_cursor.y >= 16) m_cursor.y = 0;
00058 }
00059
00060 void CCDecoder::OffsetCursor(int x, int y)
00061 {
00062 MoveCursor(m_cursor.x + x, m_cursor.y + y);
00063 }
00064
00065 void CCDecoder::PutChar(WCHAR c)
00066 {
00067 m_buff[m_cursor.y][m_cursor.x] = c;
00068 OffsetCursor(1, 0);
00069 }
00070
00071 void CCDecoder::SaveDisp(__int64 time)
00072 {
00073 CStringW str;
00074
00075 for(int row = 0; row < 16; row++)
00076 {
00077 bool fNonEmptyRow = false;
00078
00079 for(int col = 0; col < 32; col++)
00080 {
00081 if(m_disp[row][col])
00082 {
00083 CStringW str2(&m_disp[row][col]);
00084 if(fNonEmptyRow) str += ' ';
00085 str += str2;
00086 col += str2.GetLength();
00087 fNonEmptyRow = true;
00088 }
00089 }
00090
00091 if(fNonEmptyRow) str += '\n';
00092 }
00093
00094 if(str.IsEmpty()) return;
00095
00096 m_sts.Add(str, true, (int)m_time, (int)time);
00097 }
00098
00099 void CCDecoder::DecodeCC(BYTE* buff, int len, __int64 time)
00100 {
00101 if(!m_rawfn.IsEmpty())
00102 {
00103 if(FILE* f = _tfopen(m_rawfn, _T("at")))
00104 {
00105 _ftprintf(f, _T("%02d:%02d:%02d.%03d\n"),
00106 (int)(time/1000/60/60),
00107 (int)((time/1000/60)%60),
00108 (int)((time/1000)%60),
00109 (int)(time%1000));
00110
00111 for(int i = 0; i < len; i++)
00112 {
00113 _ftprintf(f, _T("%02x"), buff[i]);
00114 if(i < len-1) _ftprintf(f, _T(" "));
00115 if(i > 0 && (i&15)==15) _ftprintf(f, _T("\n"));
00116 }
00117 if(len > 0) _ftprintf(f, _T("\n\n"));
00118 fclose(f);
00119 }
00120 }
00121
00122 for(int i = 0; i < len; i++)
00123 {
00124 BYTE c = buff[i]&0x7f;
00125 if(c >= 0x20)
00126 {
00127 static WCHAR charmap[0x60] =
00128 {
00129 ' ','!','"','#','$','%','&','\'','(',')','á','+',',','-','.','/',
00130 '0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?',
00131 '@','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
00132 'P','Q','R','S','T','U','V','W','X','Y','Z','[','é',']','í','ó',
00133 'ú','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
00134 'p','q','r','s','t','u','v','w','x','y','z','ç','÷','N','n','?'
00135 };
00136
00137 PutChar(charmap[c - 0x20]);
00138 }
00139 else if(buff[i] != 0x80 && i < len-1)
00140 {
00141
00142 if(i < len-3 && buff[i] == buff[i+2] && buff[i+1] == buff[i+3])
00143 i += 2;
00144
00145 c = buff[i+1]&0x7f;
00146 if(buff[i] == 0x91 && c >= 0x20 && c < 0x30)
00147 {
00148
00149 }
00150 else if(buff[i] == 0x91 && c == 0x39)
00151 {
00152 OffsetCursor(1, 0);
00153 }
00154 else if(buff[i] == 0x91 && c >= 0x30 && c < 0x40)
00155 {
00156 static WCHAR charmap[0x10] =
00157 {
00158 0x00ae,
00159 0x00b0,
00160 0x00bd,
00161 0x00bf,
00162 0x2122,
00163 0x00a2,
00164 0x00a3,
00165 0x266a,
00166 0x00e0,
00167 0x00ff,
00168 0x00e8,
00169 0x00e2,
00170 0x00ea,
00171 0x00ee,
00172 0x00f4,
00173 0x00fb,
00174 };
00175
00176 PutChar(charmap[c - 0x30]);
00177 }
00178 else if(buff[i] == 0x92 && c >= 0x20 && c < 0x40)
00179 {
00180 static WCHAR charmap[0x20] =
00181 {
00182 0x00c0,
00183 0x00c9,
00184 0x00d3,
00185 0x00da,
00186 0x00dc,
00187 0x00fc,
00188 0x2018,
00189 0x00a1,
00190 0x002a,
00191 0x2019,
00192 0x002d,
00193 0x00a9,
00194 0x2120,
00195 0x00b7,
00196 0x201c,
00197 0x201d,
00198
00199 0x00c1,
00200 0x00c2,
00201 0x00c7,
00202 0x00c8,
00203 0x00ca,
00204 0x00cb,
00205 0x00eb,
00206 0x00ce,
00207 0x00cf,
00208 0x00ef,
00209 0x00d4,
00210 0x00d9,
00211 0x00f9,
00212 0x00db,
00213 0x00ab,
00214 0x00bb,
00215 };
00216
00217 PutChar(charmap[c - 0x20]);
00218 }
00219 else if(buff[i] == 0x13 && c >= 0x20 && c < 0x40)
00220 {
00221 static WCHAR charmap[0x20] =
00222 {
00223 0x00c3,
00224 0x00e3,
00225 0x00cd,
00226 0x00cc,
00227 0x00ec,
00228 0x00d2,
00229 0x00f2,
00230 0x00d5,
00231 0x00f5,
00232 0x007b,
00233 0x007d,
00234 0x005c,
00235 0x005e,
00236 0x005f,
00237 0x00a6,
00238 0x007e,
00239
00240 0x00c4,
00241 0x00e4,
00242 0x00d6,
00243 0x00f6,
00244 0x00df,
00245 0x00a5,
00246 0x00a4,
00247 0x007c,
00248 0x00c5,
00249 0x00e5,
00250 0x00d8,
00251 0x00f8,
00252 0x250c,
00253 0x2510,
00254 0x2514,
00255 0x2518,
00256 };
00257
00258 PutChar(charmap[c - 0x20]);
00259 }
00260 else if(buff[i] == 0x94 && buff[i+1] == 0xae)
00261 {
00262 memset(m_buff, 0, sizeof(m_buff));
00263 }
00264 else if(buff[i] == 0x94 && buff[i+1] == 0x20)
00265 {
00266 memset(m_buff, 0, sizeof(m_buff));
00267 }
00268 else if(buff[i] == 0x94 && buff[i+1] == 0x2f)
00269 {
00270 if(memcmp(m_disp, m_buff, sizeof(m_disp)) != 0)
00271 {
00272 if(m_fEndOfCaption)
00273 SaveDisp(time + (i/2)*1000/30);
00274
00275 m_fEndOfCaption = true;
00276 memcpy(m_disp, m_buff, sizeof(m_disp));
00277 m_time = time + (i/2)*1000/30;
00278 }
00279 }
00280 else if(buff[i] == 0x94 && buff[i+1] == 0x2c)
00281 {
00282 if(m_fEndOfCaption)
00283 {
00284 m_fEndOfCaption = false;
00285 SaveDisp(time + (i/2)*1000/30);
00286 }
00287
00288 memset(m_disp, 0, sizeof(m_disp));
00289 }
00290 else if(buff[i] == 0x97 && (buff[i+1] == 0xa1 || buff[i+1] == 0xa2 || buff[i+1] == 0x23))
00291 {
00292 OffsetCursor(buff[i+1]&3, 0);
00293 }
00294 else if(buff[i] == 0x91 || buff[i] == 0x92 || buff[i] == 0x15 || buff[i] == 0x16
00295 || buff[i] == 0x97 || buff[i] == 0x10 || buff[i] == 0x13 || buff[i] == 0x94)
00296 {
00297 int row = 0;
00298 switch(buff[i])
00299 {
00300 default:
00301 case 0x91: row = 0; break;
00302 case 0x92: row = 2; break;
00303 case 0x15: row = 4; break;
00304 case 0x16: row = 6; break;
00305 case 0x97: row = 8; break;
00306 case 0x10: row = 10; break;
00307 case 0x13: row = 12; break;
00308 case 0x94: row = 14; break;
00309 }
00310 if(buff[i+1]&0x20) row++;
00311
00312 int col = buff[i+1]&0xe;
00313 if(col == 0 || (col > 0 && !(buff[i+1]&0x10))) col = 0;
00314 else col <<= 1;
00315
00316 MoveCursor(col, row);
00317 }
00318 else
00319 {
00320 int iiii = 0;
00321 }
00322
00323 i++;
00324 }
00325 }
00326 }
00327
00328 void CCDecoder::ExtractCC(BYTE* buff, int len, __int64 time)
00329 {
00330 for(int i = 0; i < len-9; i++)
00331 {
00332 if(*(DWORD*)&buff[i] == 0xb2010000 && *(DWORD*)&buff[i+4] == 0xf8014343)
00333 {
00334 i += 8;
00335 int nBytes = buff[i++]&0x3f;
00336 if(nBytes > 0)
00337 {
00338 nBytes = (nBytes+1)&~1;
00339
00340 BYTE* pData1 = new BYTE[nBytes];
00341 BYTE* pData2 = new BYTE[nBytes];
00342
00343 if(pData1 && pData2)
00344 {
00345 int nBytes1 = 0, nBytes2 = 0;
00346
00347 for(int j = 0; j < nBytes && i < 0x800;)
00348 {
00349 if(buff[i++] == 0xff)
00350 {
00351 pData1[nBytes1++] = buff[i++];
00352 pData1[nBytes1++] = buff[i++];
00353 }
00354 else i+=2;
00355
00356 j++;
00357
00358 if(j >= nBytes) break;
00359
00360 if(buff[i++] == 0xff)
00361 {
00362 pData2[nBytes2++] = buff[i++];
00363 pData2[nBytes2++] = buff[i++];
00364 }
00365 else i+=2;
00366
00367 j++;
00368 }
00369
00370 if(nBytes1 > 0)
00371 DecodeCC(pData1, nBytes1, time);
00372
00373 if(nBytes2 > 0)
00374 DecodeCC(pData2, nBytes2, time);
00375 }
00376
00377 if(pData1) delete [] pData1;
00378 if(pData2) delete [] pData2;
00379 }
00380
00381 break;
00382 }
00383 }
00384 }