MythTV  0.26-pre
atscdescriptors.h
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 // Copyright (c) 2003-2004, Daniel Thor Kristjansson
00003 #ifndef _ATSC_DESCRIPTORS_H_
00004 #define _ATSC_DESCRIPTORS_H_
00005 
00006 #include <vector>
00007 using namespace std;
00008 
00009 #include <QString>
00010 #include <QMap>
00011 
00012 #include "mpegdescriptors.h"
00013 
00014 using namespace std;
00015 
00016 typedef QMap<int, const unsigned char*> IntToBuf;
00017 
00018 class MultipleStringStructure
00019 {
00020   public:
00021     MultipleStringStructure(const unsigned char *data) : _data(data)
00022     {
00023         Parse();
00024     }
00025 
00026     uint StringCount(void) const { return _data[0]; }
00027     //uimsbf for (i= 0;i< number_strings;i++) {
00028     //  ISO_639_language_code 24;
00029     int LanguageKey(uint i) const
00030         { return iso639_str3_to_key(Offset(i,-1)); }
00031     QString LanguageString(uint i) const
00032         { return iso639_key_to_str3(LanguageKey(i)); }
00033     int CanonicalLanguageKey(uint i) const
00034         { return iso639_key_to_canonical_key(LanguageKey(i)); }
00035     QString CanonicalLanguageString(uint i) const
00036         { return iso639_key_to_str3(CanonicalLanguageKey(i)); }
00037     //   uimsbf cc_type         1  3.0
00038 
00039     //  uimsbf number_segments 8;
00040     uint SegmentCount(uint i) const { return *(Offset(i,-1)+3); }
00041 
00042     //  uimsbf for (j=0;j<number_segments;j++) {
00043     //    compression_type 8;
00044     uint CompressionType(uint i, uint j) const { return *Offset(i,j); }
00045     QString CompressionTypeString(uint i, uint j) const;
00046     //    uimsbf mode 8;
00047     int Mode(int i, int j) const { return *(Offset(i,j)+1); }
00048     //    uimsbf number_bytes 8;
00049     int Bytes(int i, int j) const { return *(Offset(i,j)+2); }
00050     //    uimsbf for (k= 0;k<number_bytes;k++)
00051     //      compressed_string_byte [k] 8 bslbf;
00052     //  }
00053     //}
00054 
00055     uint GetIndexOfBestMatch(QMap<uint,uint> &langPrefs) const;
00056     QString GetBestMatch(QMap<uint,uint> &langPrefs) const;
00057 
00058     QString GetSegment(uint i, uint j) const;
00059     QString GetFullString(uint i) const;
00060 
00061     void Parse(void) const;
00062 
00063     QString toString() const;
00064 
00065   private:
00066     static QString Uncompressed(const unsigned char *buf, int len, int mode);
00067     static uint Index(int i, int j) { return (i<<8)|(j&0xff); }
00068     const unsigned char *Offset(int i, int j) const
00069         { return _ptrs[Index(i,j)]; }
00070 
00071   private:
00072     const unsigned char *_data;
00073     mutable IntToBuf _ptrs;
00074 };
00075 
00076 class CaptionServiceDescriptor : public MPEGDescriptor
00077 {
00078   public:
00079     CaptionServiceDescriptor(const unsigned char *data, int len = 300) :
00080         MPEGDescriptor(data, len, DescriptorID::caption_service)
00081     {
00082         if (_data && !Parse())
00083             _data = NULL;
00084     }
00085     //       Name             bits  loc  expected value
00086     // descriptor_tag           8   0.0       0x86
00087     // descriptor_length        8   1.0
00088     // reserved                 3   2.0       0x07
00089     // number_of_services       5   2.3
00090     uint ServicesCount() const { return _data[2]&0x1f; }
00091     //uimsbf for (i=0;i<number_of_services;i++) {
00092     //   language             8*3  0.0
00093     int LanguageKey(int i) const
00094         { return iso639_str3_to_key(Offset(i,-1)); }
00095     QString LanguageString(int i) const
00096         { return iso639_key_to_str3(LanguageKey(i)); }
00097     int CanonicalLanguageKey(int i) const
00098         { return iso639_key_to_canonical_key(LanguageKey(i)); }
00099     QString CanonicalLanguageString(int i) const
00100         { return iso639_key_to_str3(CanonicalLanguageKey(i)); }
00101     //   uimsbf cc_type         1  3.0
00102     bool Type(int i) const
00103         { return ((Offset(i,-1)[3])>>7) & 1; }
00104     //   bslbf reserved         1  3.1           1
00105     //   if (cc_type==line21) {
00106     //      reserved            5  3.2        0x1f
00107     //      line21_field        1  3.7
00108     bool Line21Field(int i) const
00109         { return bool(((Offset(i,-1)[3])) & 1); }
00110     //   } else
00111     //      cap_service_number  6  3.2
00112     int CaptionServiceNumber(int i) const
00113         { return ((Offset(i,-1)[3])) & 0x3f; }
00114     //   easy_reader            1  4.0
00115     bool EasyReader(int i) const
00116         { return bool(((Offset(i,-1)[4])>>7) & 1); }
00117     //   wide_aspect_ratio      1  4.1
00118     bool WideAspectRatio(int i) const
00119         { return bool(((Offset(i,-1)[4])>>6) & 1); }
00120     //   reserved              14  4.2      0x3fff
00121     //}                            6.0
00122     bool Parse(void);
00123     QString toString() const;
00124 
00125   private:
00126     int Index(int i, int j) const { return (i<<8) | (j & 0xff); }
00127     const unsigned char *Offset(int i, int j) const
00128         { return _ptrs[Index(i,j)]; }
00129 
00130   private:
00131     IntToBuf _ptrs;
00132 };
00133 
00134 class ContentAdvisoryDescriptor : public MPEGDescriptor
00135 {
00136   public:
00137     ContentAdvisoryDescriptor(const unsigned char *data, int len = 300) :
00138         MPEGDescriptor(data, len, DescriptorID::content_advisory)
00139     {
00140         if (_data && !Parse())
00141             _data = NULL;
00142     }
00143     //       Name             bits  loc  expected value
00144     // descriptor_tag           8   0.0       0x87
00145     // descriptor_length        8   1.0
00146     // reserved                 2   2.0       0x03
00147     // rating_region_count      6   2.2
00148     uint RatingRegionCount(void) const { return _data[2] & 0x3f; }
00149     // for (i=0; i<rating_region_count; i++) {
00150     //   rating_region          8 x+0.0
00151     uint RatingRegion(uint i) const
00152         { return *Offset(i,-1); }
00153     //   rated_dimensions       8 x+1.0
00154     uint RatedDimensions(uint i) const
00155         { return *(Offset(i,-1) + 1); }
00156     //   for (j=0;j<rated_dimensions;j++) {
00157     //     rating_dimension_j   8 y+0.0
00158     uint RatingDimension(uint i, uint j) const
00159         { return *Offset(i,j); }
00160     //     reserved             4 y+1.0       0x0f
00161     //     rating_value         4 y+1.4
00162     uint RatingValue(uint i, uint j) const
00163         { return (*(Offset(i,j) + 1)) & 0xf; }
00164     //   }
00165     //   rating_desc_length     8 x+2+(rated_dimensions*2)+0.0
00166     uint RatingDescriptionLength(uint i) const
00167         { return (*(Offset(i,-1) + 2 + (RatedDimensions(i)<<1)));  }
00168     //   rating_desc_text         x+2+(rated_dimensions*2)+1.0
00169     const MultipleStringStructure RatingDescription(uint i) const
00170     {
00171         const unsigned char *data = Offset(i,-1) + 3 + (RatedDimensions(i)<<1);
00172         return MultipleStringStructure(data);
00173     }
00174     // }
00175 
00176     bool Parse(void);
00177     QString toString() const;
00178   protected:
00179     int Index(int i, int j) const { return (i<<8)|(j&0xff); }
00180     const unsigned char *Offset(int i, int j) const
00181     {
00182         IntToBuf::const_iterator it = _ptrs.find(Index(i,j));
00183         return (it != _ptrs.end()) ? *it : NULL;
00184     }
00185     IntToBuf _ptrs;
00186 };
00187 
00188 class ComponentNameDescriptor : public MPEGDescriptor
00189 {
00190   public:
00191     ComponentNameDescriptor(const unsigned char *data, int len = 300) :
00192         MPEGDescriptor(data, len, DescriptorID::component_name)
00193     {
00194     }
00195     const MultipleStringStructure ComponentNameStrings() const
00196     {
00197         return MultipleStringStructure(_data+2);
00198     }
00199     QString toString() const
00200     {
00201         return QString("Component Name Descriptor %1")
00202             .arg(ComponentNameStrings().toString());
00203     }
00204 };
00205 
00206 
00207 // a_52a.pdf p120, Table A2
00208 class AudioStreamDescriptor : public MPEGDescriptor
00209 {
00210   public:
00211     AudioStreamDescriptor(const unsigned char *data, int len = 300) :
00212         MPEGDescriptor(data, len, DescriptorID::ac3_audio_stream) { }
00213     // descriptor_tag                        8   0.0   0x81
00214     // sample_rate_code                      3   2.0
00215     uint SampleRateCode(void) const { return (_data[2]>>5)&7; }
00216     QString SampleRateCodeString(void) const;
00217     // bsid                                  5   2.3
00218     uint bsid(void) const { return _data[2]&0x1f; }
00219     // bit_rate_code                         6   3.0
00220     uint BitRateCode(void) const { return (_data[3]>>2)&0x3f; }
00221     QString BitRateCodeString(void) const;
00222     // surround_mode                         2   3.6
00223     uint SurroundMode(void) const { return _data[3]&3; }
00224     QString SurroundModeString(void) const;
00225     /*
00226       000 Major ?
00227       001 Major ?
00228       010-111 Minor
00229       111 Karaoke Mode if acmod >= 0x2. a_52a.pdf p130
00230     */
00231     // bsmod                                 3   4.0
00232     uint BasicServiceMode(void) const { return (_data[4]>>5)&7; }
00233     // num_channels                          4   4.3
00234     uint Channels(void) const { return (_data[4]>>1)&0xf; }
00235     QString ChannelsString(void) const;
00236 
00237     // full service that can be presented alone to listener?
00238     // full_svc                              1   4.7
00239     bool FullService(void) const { return bool((_data[4])&1); }
00240 
00241     // langcod                               8   5.0
00242     // ignore for language specification
00243     uint LanguageCode(void) const { return _data[5]; }
00244     // if(num_channels==0) /* 1+1 mode */
00245     //   langcod2                            8   6.0
00246     // ignore for language specification
00247     uint LanguageCode2(void) const { return _data[6]; }
00248 
00249     // if(bsmod<2) {
00250     //  mainid                               3   7.0/6.0
00251     uint MainID(void) const
00252     {
00253         return _data[(Channels()==0)?7:6]>>5;
00254     }
00255     //  reserved                             5   7.3/6.3
00256     //uint reserved(void) const { return _data[7]&0x1f; }
00257     // } else asvcflags                      8   7.0/6.0
00258     uint AServiceFlags(void) const
00259     {
00260         return _data[(Channels()==0)?7:6];
00261     }
00262 
00263     // textlen                               7   8.0/7.0
00264     uint TextLength(void) const
00265     {
00266         return _data[(Channels()==0)?8:7]>>1;
00267     }
00268 
00269     /* If this bit is a  1 , the text is encoded as 1-byte characters
00270        using the ISO Latin-1 alphabet (ISO 8859-1). If this bit is a 0,
00271        the text is encoded with 2-byte unicode characters. */
00272     // text_code 1 bslbf
00273     bool IsTextLatin1(void) const
00274     {
00275         return bool(_data[(Channels()==0)?8:7]&1);
00276     }
00277     // for(i=0; i<M; i++) {
00278     //        text[i] 8 bslbf
00279     // }
00280     QString Text(void) const
00281     { // TODO
00282 #if 0
00283         char *tmp = new char[TextLength()+2];
00284         if (IsTextLatin1())
00285         {
00286             memcpy(tmp, &_data[(Channels()==0)?9:8], TextLength());
00287             tmp[TextLength()]=0;
00288             for (uint i=0; i<TextLength(); i++)
00289                 if (!tmp[i]) tmp[i]='H';
00290             QString str(tmp);
00291             delete[] tmp;
00292             return str;
00293         }
00294         else
00295         {
00296             QString str; int len = TextLength();
00297             const unsigned char *buf = (&_data[(Channels()==0)?9:8]);
00298             const unsigned short* ustr =
00299                 reinterpret_cast<const unsigned short*>(buf);
00300             for (int j=0; j<(len>>1); j++)
00301                 str.append( QChar( (ustr[j]<<8) | (ustr[j]>>8) ) );
00302             return str;
00303         }
00304 #endif
00305         return QString("TODO");
00306     }
00307     // for(i=0; i<N; i++) {
00308     //   additional_info[i] N×8 bslbf
00309     // }
00310 
00311     QString toString() const;
00312 };
00313 
00318 class ContentIdentifierDescriptor : public MPEGDescriptor
00319 {
00320     ContentIdentifierDescriptor(const unsigned char *data, int len = 300) :
00321         MPEGDescriptor(data, len, DescriptorID::atsc_content_identifier) { }
00322     // descriptor_tag                        8   0.0  0xB6
00323     // descriptor_length                     8   1.0
00324     // content_ID_structure
00325     //   ID_system                           8   2.0
00326     //        0x00 ISAN (ISO 15706[1])
00327     //        0x01 V-ISAN (ISO 20925-1[2])
00328     //        0x02-0xFF ATSC Reserved
00329     //   ID_length                           8   3.0
00330     //   content_identifier                  v   4.0
00331 };
00332 
00340 class ExtendedChannelNameDescriptor : public MPEGDescriptor
00341 {
00342   public:
00343     ExtendedChannelNameDescriptor(const unsigned char *data, int len = 300) :
00344         MPEGDescriptor(data, len, DescriptorID::extended_channel_name) { }
00345     MultipleStringStructure LongChannelName(void) const;
00346     QString LongChannelNameString(void) const;
00347     QString toString() const;
00348 };
00349 
00350 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends