|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00002 // Copyright (c) 2003-2004, Daniel Thor Kristjansson 00003 00004 #include <algorithm> 00005 using namespace std; 00006 00007 #include "atscdescriptors.h" 00008 #include "mythlogging.h" 00009 #include "iso639.h" 00010 #include "atsc_huffman.h" 00011 00012 using namespace std; 00013 00014 00015 QString MultipleStringStructure::CompressionTypeString(uint i, uint j) const 00016 { 00017 uint ct = CompressionType(i, j); 00018 if (0 == ct) 00019 return QString("no compression"); 00020 if (1 == ct) 00021 return QString("Huffman Coding using C.4, C.5"); 00022 if (2 == ct) 00023 return QString("Huffman Coding using C.6, C.7"); 00024 if (ct < 0xaf) 00025 return QString("reserved"); 00026 return QString("compression not used by ATSC in North America, unknown"); 00027 } 00028 00029 QString MultipleStringStructure::toString() const 00030 { 00031 QString str; 00032 if (1 == StringCount() && 1 == SegmentCount(0)) 00033 { 00034 str.append(QString("lang(%1) ").arg(LanguageString(0))); 00035 if (0 != Bytes(0, 0)) 00036 str.append(GetSegment(0, 0)); 00037 return str; 00038 } 00039 00040 str.append(QString("MultipleStringStructure count(%1)") 00041 .arg(StringCount())); 00042 00043 for (uint i = 0; i < StringCount(); i++) 00044 { 00045 str.append(QString(" String #%1 lang(%2:%3)") 00046 .arg(i).arg(LanguageString(i)) 00047 .arg(LanguageKey(i))); 00048 00049 if (SegmentCount(i) > 1) 00050 str.append(QString(" segment count(%1)").arg(SegmentCount(i))); 00051 00052 for (uint j=0; j<SegmentCount(i); j++) 00053 str.append(QString(" Segment #%1 ct(%2) str(%3)").arg(j) 00054 .arg(CompressionType(i, j)).arg(GetSegment(i, j))); 00055 } 00056 00057 return str; 00058 } 00059 00060 static uint maxPriority(const QMap<uint,uint> &langPrefs) 00061 { 00062 uint max_pri = 0; 00063 QMap<uint,uint>::const_iterator it = langPrefs.begin(); 00064 for (; it != langPrefs.end(); ++it) 00065 max_pri = max(max_pri, *it); 00066 return max_pri; 00067 } 00068 00069 uint MultipleStringStructure::GetIndexOfBestMatch( 00070 QMap<uint,uint> &langPrefs) const 00071 { 00072 uint match_idx = 0; 00073 uint match_pri = 0; 00074 00075 for (uint i = 0; i < StringCount(); i++) 00076 { 00077 QMap<uint,uint>::const_iterator it = 00078 langPrefs.find(CanonicalLanguageKey(i)); 00079 if ((it != langPrefs.end()) && (*it > match_pri)) 00080 { 00081 match_idx = i; 00082 match_pri = *it; 00083 } 00084 } 00085 00086 if (match_pri) 00087 return match_idx; 00088 00089 if (StringCount()) 00090 langPrefs[CanonicalLanguageKey(0)] = maxPriority(langPrefs) + 1; 00091 00092 return 0; 00093 } 00094 00095 QString MultipleStringStructure::GetBestMatch(QMap<uint,uint> &langPrefs) const 00096 { 00097 if (StringCount()) 00098 return GetFullString(GetIndexOfBestMatch(langPrefs)); 00099 return QString::null; 00100 } 00101 00102 QString MultipleStringStructure::GetSegment(uint i, uint j) const 00103 { 00104 const unsigned char* buf = (Offset(i, j)+3); 00105 int len = Bytes(i, j); 00106 00107 if (len <= 0) 00108 return ""; 00109 00110 int ct = CompressionType(i, j); 00111 00112 if (ct == 0) 00113 return Uncompressed(buf, len, Mode(i, j)); 00114 00115 if (ct < 3) 00116 return atsc_huffman1_to_string(buf, len, ct); 00117 00118 return QString("MSS unknown text compression %1").arg(ct); 00119 } 00120 00121 QString MultipleStringStructure::GetFullString(uint i) const 00122 { 00123 QString tmp = ""; 00124 for (uint j = 0; j < SegmentCount(i); j++) 00125 tmp += GetSegment(i, j); 00126 return tmp; 00127 } 00128 00129 QString MultipleStringStructure::Uncompressed( 00130 const unsigned char* buf, int len, int mode) { 00131 00132 QString str=QString(""); 00133 if (mode<=6 || 00134 (9<=mode && mode<=0xe) || 00135 (0x10==mode) || 00136 (0x20<=mode && mode<=0x27) || 00137 (0x30<=mode && mode<=0x33)) { // basic runlength encoding 00138 int hb=mode<<8; 00139 for (int j=0; j<len; j++) 00140 { 00141 #if 0 00142 LOG(VB_GENERAL, LOG_DEBUG, QString("str.append(0x%1:0x%2) -> %3") 00143 .arg(mode, 0, 16) .arg(buf[j], 0, 16) .arg(QChar(hb|buf[j]))); 00144 #endif 00145 str.append( QChar( hb|buf[j] ) ); 00146 } 00147 } else if (mode==0x3e) { 00148 // Standard Compression Scheme for Unicode (SCSU) 00149 str=QString("TODO SCSU encoding"); 00150 } else if (mode==0x3f) { // Unicode, UTF-16 Form 00151 const unsigned short* ustr = 00152 reinterpret_cast<const unsigned short*>(buf); 00153 for (int j=0; j<(len>>1); j++) 00154 str.append( QChar( (ustr[j]<<8) | (ustr[j]>>8) ) ); 00155 } else if (0x40<=mode && mode<=0x41) 00156 str = QString("TODO Tawain Characters"); 00157 else if (0x48==mode) 00158 str = QString("TODO South Korean Characters"); 00159 else 00160 str = QString("unknown character encoding mode(%0)").arg(mode); 00161 return str; 00162 } 00163 00164 void MultipleStringStructure::Parse(void) const 00165 { 00166 _ptrs.clear(); 00167 _ptrs[Index(0,-1)] = _data + 1; 00168 for (uint i = 0; i < StringCount(); i++) 00169 { 00170 _ptrs[Index(i,0)] = Offset(i,-1) + 4; 00171 uint j = 0; 00172 for (; j < SegmentCount(i); j++) 00173 _ptrs[Index(i,j+1)] = Offset(i,j) + Bytes(i,j) + 3; 00174 _ptrs[Index(i+1,-1)] = Offset(i,j); 00175 } 00176 } 00177 00178 bool CaptionServiceDescriptor::Parse(void) 00179 { 00180 _ptrs.clear(); 00181 _ptrs[Index(0,-1)] = _data+3; 00182 00183 for (uint i = 0; i < ServicesCount(); i++) 00184 _ptrs[Index(i+1,-1)] = Offset(i,-1) + 6; 00185 00186 return true; 00187 } 00188 00189 QString CaptionServiceDescriptor::toString(void) const 00190 { 00191 QString str("Caption Service Descriptor "); 00192 str.append(QString("services(%2)").arg(ServicesCount())); 00193 00194 for (uint i = 0; i < ServicesCount(); i++) 00195 { 00196 str.append(QString("\n lang(%1) type(%2) ") 00197 .arg(LanguageString(i)).arg(Type(i))); 00198 str.append(QString("easy_reader(%1) wide(%2) ") 00199 .arg(EasyReader(i)).arg(WideAspectRatio(i))); 00200 if (Type(i)) 00201 str.append(QString("service_num(%1)") 00202 .arg(CaptionServiceNumber(i))); 00203 else 00204 str.append(QString("line_21_field(%1)").arg(Line21Field(i))); 00205 } 00206 00207 return str; 00208 } 00209 00210 bool ContentAdvisoryDescriptor::Parse(void) 00211 { 00212 _ptrs.clear(); 00213 _ptrs[Index(0,-1)] = _data + 2; 00214 00215 for (uint i = 0; i < RatingRegionCount(); i++) 00216 { 00217 _ptrs[Index(i,0)] = Offset(i,-1)+2; 00218 uint j = 0; 00219 for (; j < RatedDimensions(i); j++) 00220 _ptrs[Index(i,j+1)] = Offset(i,j) + 2; 00221 const unsigned char *tmp = Offset(i,-1) + 3 + (RatedDimensions(i)<<1); 00222 uint len = RatingDescriptionLength(i); 00223 _ptrs[Index(i+1,-1)] = tmp + len; 00224 } 00225 00226 return true; 00227 } 00228 00229 QString ContentAdvisoryDescriptor::toString() const 00230 { 00231 return "ContentAdvisoryDescriptor::toString(): Not implemented"; 00232 } 00233 00234 QString AudioStreamDescriptor::SampleRateCodeString(void) const 00235 { 00236 static const char* asd[] = 00237 { 00238 "48kbps", "44.1kbps", "32kbps", "Reserved", 00239 "48kbps or 44.1kbps", "48kbps or 32kbps", 00240 "44.1kbps or 32kbps", "48kbps or 44.1kbps or 32kbps" 00241 }; 00242 return QString(asd[SampleRateCode()]); 00243 } 00244 00245 QString AudioStreamDescriptor::BitRateCodeString(void) const 00246 { 00247 static const char* ebr[19] = 00248 { 00249 "=32kbps", "=40kbps", "=48kbps", "=56kbps", "=64kbps", 00250 "=80kbps", "=96kbps", "=112kbps", "=128kbps", "=160kbps", 00251 "=192kbps", "=224kbps", "=256kbps", "=320kbps", "=384kbps", 00252 "=448kbps", "=512kbps", "=576kbps", "=640kbps" 00253 }; 00254 static const char* ubr[19] = 00255 { 00256 "<=32kbps", "<=40kbps", "<=48kbps", "<=56kbps", "<=64kbps", 00257 "<=80kbps", "<=96kbps", "<=112kbps", "<=128kbps", "<=160kbps", 00258 "<=192kbps","<=224kbps", "<=256kbps", "<=320kbps", "<=384kbps", 00259 "<=448kbps","<=512kbps", "<=576kbps", "<=640kbps" 00260 }; 00261 00262 if (BitRateCode() <= 18) 00263 return QString(ebr[BitRateCode()]); 00264 else if ((BitRateCode() >= 32) && (BitRateCode() <= 50)) 00265 return QString(ubr[BitRateCode()-32]); 00266 00267 return QString("Unknown Bit Rate Code"); 00268 } 00269 00270 QString AudioStreamDescriptor::SurroundModeString(void) const 00271 { 00272 static const char* sms[] = 00273 { 00274 "Not indicated", 00275 "Not Dolby surround encoded", 00276 "Dolby surround encoded", 00277 "Reserved", 00278 }; 00279 return QString(sms[SurroundMode()]); 00280 } 00281 00282 QString AudioStreamDescriptor::ChannelsString(void) const 00283 { 00284 static const char* cs[] = 00285 { 00286 "1 + 1", "1/0", "2/0", "3/0", 00287 "2/1", "3/1", "2/2 ", "3/2", 00288 "1", "<= 2", "<= 3", "<= 4", 00289 "<= 5", "<= 6", "Reserved", "Reserved" 00290 }; 00291 return cs[Channels()]; 00292 } 00293 00294 QString AudioStreamDescriptor::toString() const 00295 { 00296 QString str; 00297 str.append(QString("Audio Stream Descriptor ")); 00298 str.append(QString(" full_srv(%1) sample_rate(%2) bit_rate(%3, %4)\n") 00299 .arg(FullService()).arg(SampleRateCodeString()) 00300 .arg(BitRateCodeString()).arg(BitRateCode())); 00301 str.append(QString(" bsid(%1) bs_mode(%2) channels(%3) Dolby(%4)\n") 00302 .arg(bsid()).arg(BasicServiceMode()) 00303 .arg(ChannelsString()).arg(SurroundModeString())); 00304 00305 /* 00306 str.append(QString(" language code: %1").arg(languageCode())); 00307 if (0==channels()) { 00308 str.append(QString(" language code 2: %1").arg(languageCode2())); 00309 } 00310 */ 00311 00312 if (BasicServiceMode() < 2) 00313 str.append(QString(" mainID(%1) ").arg(MainID())); 00314 else 00315 str.append(QString(" associated_service(0x%1) ") 00316 .arg(AServiceFlags(),0,16)); 00317 00318 if (TextLength()) 00319 { 00320 str.append(QString("isLatin-1(%1) ") 00321 .arg(IsTextLatin1() ? "true" : "false")); 00322 str.append(QString("text_length(%1) ").arg(TextLength())); 00323 str.append(QString("text(%1)").arg(Text())); 00324 } 00325 return str; 00326 } 00327 00332 MultipleStringStructure ExtendedChannelNameDescriptor::LongChannelName( 00333 void) const 00334 { 00335 return MultipleStringStructure(_data + 2); 00336 } 00337 00342 QString ExtendedChannelNameDescriptor::LongChannelNameString(void) const 00343 { 00344 QString str = ""; 00345 MultipleStringStructure mstr = LongChannelName(); 00346 00347 for (uint i = 0; i < mstr.StringCount(); i++) 00348 str += mstr.GetFullString(i); 00349 00350 return str; 00351 } 00352 00353 QString ExtendedChannelNameDescriptor::toString() const 00354 { 00355 return QString("ExtendedChannelNameDescriptor: '%1'") 00356 .arg(LongChannelNameString()); 00357 }
1.7.6.1