CCDecoder.cpp

00001 /* 
00002  *      Copyright (C) 2003-2005 Gabest
00003  *      http://www.gabest.org
00004  *
00005  *  This Program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2, or (at your option)
00008  *  any later version.
00009  *   
00010  *  This Program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
00013  *  GNU General Public License for more details.
00014  *   
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with GNU Make; see the file COPYING.  If not, write to
00017  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
00018  *  http://www.gnu.org/copyleft/gpl.html
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                         // codes and special characters are supposed to be doubled
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) // formating
00147                         {
00148                                 // TODO
00149                         }
00150                         else if(buff[i] == 0x91 && c == 0x39) // transparent space
00151                         {
00152                                 OffsetCursor(1, 0);
00153                         }
00154                         else if(buff[i] == 0x91 && c >= 0x30 && c < 0x40) // special characters
00155                         {
00156                                 static WCHAR charmap[0x10] =
00157                                 {
00158                                         0x00ae, // (r)egistered
00159                                         0x00b0, // degree
00160                                         0x00bd, // 1/2
00161                                         0x00bf, // inverted question mark
00162                                         0x2122, // trade mark
00163                                         0x00a2, // cent
00164                                         0x00a3, // pound
00165                                         0x266a, // music
00166                                         0x00e0, // a`
00167                                         0x00ff, // transparent space, handled above
00168                                         0x00e8, // e`
00169                                         0x00e2, // a^
00170                                         0x00ea, // e^
00171                                         0x00ee, // i^
00172                                         0x00f4, // o^
00173                                         0x00fb, // u^
00174                                 };
00175 
00176                                 PutChar(charmap[c - 0x30]);
00177                         }
00178                         else if(buff[i] == 0x92 && c >= 0x20 && c < 0x40) // extended characters
00179                         {
00180                                 static WCHAR charmap[0x20] =
00181                                 {
00182                                         0x00c0, // A'
00183                                         0x00c9, // E'
00184                                         0x00d3, // O'
00185                                         0x00da, // U'
00186                                         0x00dc, // U:
00187                                         0x00fc, // u:
00188                                         0x2018, // `
00189                                         0x00a1, // inverted !
00190                                         0x002a, // *
00191                                         0x2019, // '
00192                                         0x002d, // -
00193                                         0x00a9, // (c)opyright
00194                                         0x2120, // SM
00195                                         0x00b7, // . (dot in the middle)
00196                                         0x201c, // inverted "
00197                                         0x201d, // "
00198 
00199                                         0x00c1, // A`
00200                                         0x00c2, // A^
00201                                         0x00c7, // C,
00202                                         0x00c8, // E`
00203                                         0x00ca, // E^
00204                                         0x00cb, // E:
00205                                         0x00eb, // e:
00206                                         0x00ce, // I^
00207                                         0x00cf, // I:
00208                                         0x00ef, // i:
00209                                         0x00d4, // O^
00210                                         0x00d9, // U`
00211                                         0x00f9, // u`
00212                                         0x00db, // U^
00213                                         0x00ab, // <<
00214                                         0x00bb, // >>
00215                                 };
00216 
00217                                 PutChar(charmap[c - 0x20]);
00218                         }
00219                         else if(buff[i] == 0x13 && c >= 0x20 && c < 0x40) // more extended characters
00220                         {
00221                                 static WCHAR charmap[0x20] =
00222                                 {
00223                                         0x00c3, // A~
00224                                         0x00e3, // a~
00225                                         0x00cd, // I'
00226                                         0x00cc, // I`
00227                                         0x00ec, // i`
00228                                         0x00d2, // O`
00229                                         0x00f2, // o`
00230                                         0x00d5, // O~
00231                                         0x00f5, // o~
00232                                         0x007b, // {
00233                                         0x007d, // }
00234                                         0x005c, // /* \ */
00235                                         0x005e, // ^
00236                                         0x005f, // _
00237                                         0x00a6, // |
00238                                         0x007e, // ~
00239 
00240                                         0x00c4, // A:
00241                                         0x00e4, // a:
00242                                         0x00d6, // O:
00243                                         0x00f6, // o:
00244                                         0x00df, // B (ss in german)
00245                                         0x00a5, // Y=
00246                                         0x00a4, // ox
00247                                         0x007c, // |
00248                                         0x00c5, // Ao
00249                                         0x00e5, // ao
00250                                         0x00d8, // O/
00251                                         0x00f8, // o/
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) // Erase Non-displayed [buffer] Memory
00261                         {
00262                                 memset(m_buff, 0, sizeof(m_buff));
00263                         }
00264                         else if(buff[i] == 0x94 && buff[i+1] == 0x20) // Resume Caption Loading
00265                         {
00266                                 memset(m_buff, 0, sizeof(m_buff));
00267                         }
00268                         else if(buff[i] == 0x94 && buff[i+1] == 0x2f) // End Of Caption
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) // Erase Displayed Memory
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)) // Tab Over
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) // curpos, color, underline
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 }

Generated on Tue Dec 13 14:47:53 2005 for guliverkli by  doxygen 1.4.5