00001
00002
00003
00004 #include <algorithm>
00005 using namespace std;
00006
00007 #include "atscdescriptors.h"
00008 #include "mythcontext.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
00142 str.append( QChar( hb|buf[j] ) );
00143 }
00144 } else if (mode==0x3e) {
00145
00146 str=QString("TODO SCSU encoding");
00147 } else if (mode==0x3f) {
00148 const unsigned short* ustr =
00149 reinterpret_cast<const unsigned short*>(buf);
00150 for (int j=0; j<(len>>1); j++)
00151 str.append( QChar( (ustr[j]<<8) | (ustr[j]>>8) ) );
00152 } else if (0x40<=mode && mode<=0x41)
00153 str = QString("TODO Tawain Characters");
00154 else if (0x48==mode)
00155 str = QString("TODO South Korean Characters");
00156 else
00157 str = QString("unknown character encoding mode(%0)").arg(mode);
00158 return str;
00159 }
00160
00161 void MultipleStringStructure::Parse(void) const
00162 {
00163 _ptrs.clear();
00164 _ptrs[Index(0,-1)] = _data + 1;
00165 for (uint i = 0; i < StringCount(); i++)
00166 {
00167 _ptrs[Index(i,0)] = Offset(i,-1) + 4;
00168 uint j = 0;
00169 for (; j < SegmentCount(i); j++)
00170 _ptrs[Index(i,j+1)] = Offset(i,j) + Bytes(i,j);
00171 _ptrs[Index(i+1,-1)] = Offset(i,j);
00172 }
00173 }
00174
00175 void CaptionServiceDescriptor::Parse(void) const
00176 {
00177 _ptrs.clear();
00178 _ptrs[Index(0,-1)] = _data+3;
00179
00180 for (uint i = 0; i < ServicesCount(); i++)
00181 _ptrs[Index(i+1,-1)] = Offset(i,-1) + 6;
00182 }
00183
00184 QString CaptionServiceDescriptor::toString(void) const
00185 {
00186 QString str("Caption Service Descriptor ");
00187 str.append(QString("services(%2)").arg(ServicesCount()));
00188
00189 for (uint i = 0; i < ServicesCount(); i++)
00190 {
00191 str.append(QString("\n lang(%1) type(%2) ")
00192 .arg(LanguageString(i)).arg(Type(i)));
00193 str.append(QString("easy_reader(%1) wide(%2) ")
00194 .arg(EasyReader(i)).arg(WideAspectRatio(i)));
00195 if (Type(i))
00196 str.append(QString("service_num(%1)")
00197 .arg(CaptionServiceNumber(i)));
00198 else
00199 str.append(QString("line_21_field(%1)").arg(Line21Field(i)));
00200 }
00201
00202 return str;
00203 }
00204
00205 void ContentAdvisoryDescriptor::Parse(void) const
00206 {
00207 _ptrs.clear();
00208 _ptrs[Index(0,-1)] = _data + 2;
00209
00210 for (uint i = 0; i < RatingRegionCount(); i++)
00211 {
00212 _ptrs[Index(i,0)] = Offset(i,-1)+2;
00213 uint j = 0;
00214 for (; j < RatedDimensions(i); j++)
00215 _ptrs[Index(i,j+1)] = Offset(i,j) + 2;
00216 const unsigned char *tmp = Offset(i,-1) + 3 + (RatedDimensions(i)<<1);
00217 uint len = RatingDescriptionLength(i);
00218 _ptrs[Index(i+1,-1)] = tmp + len;
00219 }
00220 }
00221
00222 QString ContentAdvisoryDescriptor::toString() const
00223 {
00224 return "ContentAdvisoryDescriptor::toString(): Not implemented";
00225 }
00226
00227 QString AudioStreamDescriptor::SampleRateCodeString(void) const
00228 {
00229 static const char* asd[] =
00230 {
00231 "48kbps", "44.1kbps", "32kbps", "Reserved",
00232 "48kbps or 44.1kbps", "48kbps or 32kbps",
00233 "44.1kbps or 32kbps", "48kbps or 44.1kbps or 32kbps"
00234 };
00235 return QString(asd[SampleRateCode()]);
00236 }
00237
00238 QString AudioStreamDescriptor::BitRateCodeString(void) const
00239 {
00240 static const char* ebr[19] =
00241 {
00242 "=32kbps", "=40kbps", "=48kbps", "=56kbps", "=64kbps",
00243 "=80kbps", "=96kbps", "=112kbps", "=128kbps", "=160kbps",
00244 "=192kbps", "=224kbps", "=256kbps", "=320kbps", "=384kbps",
00245 "=448kbps", "=512kbps", "=576kbps", "=640kbps"
00246 };
00247 static const char* ubr[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
00255 if (BitRateCode() <= 18)
00256 return QString(ebr[BitRateCode()]);
00257 else if ((BitRateCode() >= 32) && (BitRateCode() <= 50))
00258 return QString(ubr[BitRateCode()-32]);
00259
00260 return QString("Unknown Bit Rate Code");
00261 }
00262
00263 QString AudioStreamDescriptor::SurroundModeString(void) const
00264 {
00265 static const char* sms[] =
00266 {
00267 "Not indicated",
00268 "Not Dolby surround encoded",
00269 "Dolby surround encoded",
00270 "Reserved",
00271 };
00272 return QString(sms[SurroundMode()]);
00273 }
00274
00275 QString AudioStreamDescriptor::ChannelsString(void) const
00276 {
00277 static const char* cs[] =
00278 {
00279 "1 + 1", "1/0", "2/0", "3/0",
00280 "2/1", "3/1", "2/2 ", "3/2",
00281 "1", "<= 2", "<= 3", "<= 4",
00282 "<= 5", "<= 6", "Reserved", "Reserved"
00283 };
00284 return cs[Channels()];
00285 }
00286
00287 QString AudioStreamDescriptor::toString() const
00288 {
00289 QString str;
00290 str.append(QString("Audio Stream Descriptor "));
00291 str.append(QString(" full_srv(%1) sample_rate(%2) bit_rate(%3, %4)\n")
00292 .arg(FullService()).arg(SampleRateCodeString())
00293 .arg(BitRateCodeString()).arg(BitRateCode()));
00294 str.append(QString(" bsid(%1) bs_mode(%2) channels(%3) Dolby(%4)\n")
00295 .arg(bsid()).arg(BasicServiceMode())
00296 .arg(ChannelsString()).arg(SurroundModeString()));
00297
00298
00299
00300
00301
00302
00303
00304
00305 if (BasicServiceMode() < 2)
00306 str.append(QString(" mainID(%1) ").arg(MainID()));
00307 else
00308 str.append(QString(" associated_service(0x%1) ")
00309 .arg(AServiceFlags(),0,16));
00310
00311 if (TextLength())
00312 {
00313 str.append(QString("isLatin-1(%1) ")
00314 .arg(IsTextLatin1() ? "true" : "false"));
00315 str.append(QString("text_length(%1) ").arg(TextLength()));
00316 str.append(QString("text(%1)").arg(Text()));
00317 }
00318 return str;
00319 }
00320
00326 ExtendedChannelNameDescriptor::ExtendedChannelNameDescriptor(
00327 const unsigned char *data) : MPEGDescriptor(data)
00328 {
00329 assert(DescriptorTag() == DescriptorID::extended_channel_name);
00330 }
00331
00336 MultipleStringStructure ExtendedChannelNameDescriptor::LongChannelName(
00337 void) const
00338 {
00339 return MultipleStringStructure(_data + 2);
00340 }
00341
00346 QString ExtendedChannelNameDescriptor::LongChannelNameString(void) const
00347 {
00348 QString str = "";
00349 MultipleStringStructure mstr = LongChannelName();
00350
00351 for (uint i = 0; i < mstr.StringCount(); i++)
00352 str += mstr.GetFullString(i);
00353
00354 return str;
00355 }
00356
00357 QString ExtendedChannelNameDescriptor::toString() const
00358 {
00359 return QString("ExtendedChannelNameDescriptor: '%1'")
00360 .arg(LongChannelNameString());
00361 }