00001
00002
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)) {
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
00149 str=QString("TODO SCSU encoding");
00150 } else if (mode==0x3f) {
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
00307
00308
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 }