Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 
     19 #include "oscl_string_utils.h"
     20 #include "common_info.h"
     21 #include "rtsp_range_utils.h"
     22 #include "oscl_str_ptr_len.h"
     23 #include "oscl_stdstring.h"
     24 #include "sdp_parsing_utils.h"
     25 #include "oscl_utf8conv.h"
     26 #include "oscl_snprintf.h"
     27 #include "oscl_bin_stream.h"
     28 
     29 #define BYTE_ORDER_MASK 0xFEFF
     30 static const char PVSDPMETADATA_LANG_CODE[] = ";iso-639-2-lang=";
     31 static const char PVSDPMETADATA_RATING_ENTITY[] = ";rating-entity=";
     32 static const char PVSDPMETADATA_RATING_CRITERIA[] = ";rating-criteria=";
     33 static const char PVSDPMETADATA_CLASSIFICATION_ENTITY[] = ";classification-entity=";
     34 static const char PVSDPMETADATA_CLASSFICATION_TABLE[] = ";classification-table=";
     35 
     36 bool get_next_line(const char *start_ptr, const char * end_ptr,
     37                    const char *& line_start,
     38                    const char *& line_end)
     39 {
     40     // Finds the boundaries of the next non-empty line within start
     41     // and end ptrs
     42 
     43     // This initializes line_start to the first non-whitespace character
     44     line_start = skip_whitespace_and_line_term(start_ptr, end_ptr);
     45 
     46     line_end = skip_to_line_term(line_start, end_ptr);
     47 
     48     return (line_start < end_ptr);
     49 
     50 }
     51 
     52 bool sdp_decodebase64(uint8* aInBuf, uint32 aInBufLen,
     53                       uint8* aOutBuf, uint32& aOutBufLen, uint32 aMaxOutBufLen)
     54 {
     55     oscl_memset(aOutBuf, 0, aMaxOutBufLen);
     56     aOutBufLen = 0;
     57 
     58     int i;
     59     uint8 dtable[256];
     60 
     61     for (i = 0; i < 255; i++)
     62     {
     63         dtable[i] = 0x80;
     64     }
     65     for (i = 'A'; i <= 'I'; i++)
     66     {
     67         dtable[i] = 0 + (i - 'A');
     68     }
     69     for (i = 'J'; i <= 'R'; i++)
     70     {
     71         dtable[i] = 9 + (i - 'J');
     72     }
     73     for (i = 'S'; i <= 'Z'; i++)
     74     {
     75         dtable[i] = 18 + (i - 'S');
     76     }
     77     for (i = 'a'; i <= 'i'; i++)
     78     {
     79         dtable[i] = 26 + (i - 'a');
     80     }
     81     for (i = 'j'; i <= 'r'; i++)
     82     {
     83         dtable[i] = 35 + (i - 'j');
     84     }
     85     for (i = 's'; i <= 'z'; i++)
     86     {
     87         dtable[i] = 44 + (i - 's');
     88     }
     89     for (i = '0'; i <= '9'; i++)
     90     {
     91         dtable[i] = 52 + (i - '0');
     92     }
     93     dtable[(int)'+'] = 62;
     94     dtable[(int)'/'] = 63;
     95     dtable[(int)'='] = 0;
     96 
     97     uint32 read_count = 0;
     98     uint32 write_count = 0;
     99     while (read_count < aInBufLen)
    100     {
    101         uint8 a[4], b[4], o[3];
    102 
    103         for (i = 0; i < 4; i++)
    104         {
    105             uint8 c = *(aInBuf++);
    106             read_count++;
    107 
    108             if (read_count > aInBufLen)
    109             {
    110                 //Input incomplete
    111                 return false;
    112             }
    113             if (dtable[(int)c]&0x80)
    114             {
    115                 //Illegal character in
    116                 //return false;
    117                 i--;
    118                 continue;
    119             }
    120             a[i] = (uint8)c;
    121             b[i] = (uint8)dtable[(int)c];
    122         }
    123         o[0] = (b[0] << 2) | (b[1] >> 4);
    124         o[1] = (b[1] << 4) | (b[2] >> 2);
    125         o[2] = (b[2] << 6) | b[3];
    126         i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
    127         oscl_memcpy(aOutBuf, o, i);
    128         aOutBuf += i;
    129         write_count += i;
    130         if (write_count > aMaxOutBufLen)
    131         {
    132             return false;
    133         }
    134         if (i < 3)
    135         {
    136             break;
    137         }
    138     }
    139     aOutBufLen = write_count;
    140     return true;
    141 }
    142 
    143 
    144 bool parseQoEMetrics(const char *start_ptr, const char *end_ptr, QoEMetricsType &qoeMetrics)
    145 {
    146     const char *sptr = start_ptr;
    147     const char *eptr = end_ptr;
    148 
    149     sptr = skip_whitespace_and_line_term(sptr, end_ptr);
    150 
    151     StrPtrLen rate("rate=");
    152     StrPtrLen range("range:");
    153 
    154     if (!oscl_strncmp(sptr, "{", 1))
    155         sptr = sptr + 1;
    156     else
    157         return false;
    158 
    159     sptr = skip_whitespace_and_line_term(sptr, end_ptr);
    160     if (sptr > eptr)
    161         return false;
    162 
    163     while (sptr < end_ptr)
    164     {
    165 
    166         if (!oscl_strncmp(sptr, "Initial_Buffering_Duration",
    167                           oscl_strlen("Initial_Buffering_Duration")))
    168         {
    169             qoeMetrics.name[QoEMetricsType::INITIAL_BUFFERING_DURATION] = true;
    170             sptr = sptr + oscl_strlen("Initial_Buffering_Duration");
    171         }
    172         else if (!oscl_strncmp(sptr, "Rebuffering_Duration",
    173                                oscl_strlen("Rebuffering_Duration")))
    174         {
    175             qoeMetrics.name[QoEMetricsType::REBUFFERING_DURATION] = true;
    176             sptr = sptr + oscl_strlen("Rebuffering_Duration");
    177         }
    178         else if (!oscl_strncmp(sptr, "Corruption_Duration",
    179                                oscl_strlen("Corruption_Duration")))
    180         {
    181             qoeMetrics.name[QoEMetricsType::CORRUPTION_DURATION] = true;
    182             sptr = sptr + oscl_strlen("Corruption_Duration");
    183         }
    184         else if (!oscl_strncmp(sptr, "Succssive_Loss",
    185                                oscl_strlen("Succssive_Loss")))
    186         {
    187             qoeMetrics.name[QoEMetricsType::SUCESSIVE_LOSS] = true;
    188             sptr = sptr + oscl_strlen("Succssive_Loss");
    189         }
    190         else if (!oscl_strncmp(sptr, "Framerate_Deviation",
    191                                oscl_strlen("Framerate_Deviation")))
    192         {
    193             qoeMetrics.name[QoEMetricsType::FRAMERATE_DEVIATION] = true;
    194             sptr = sptr + oscl_strlen("Framerate_Deviation");
    195         }
    196         else if (!oscl_strncmp(sptr, "Jitter_Duration",
    197                                oscl_strlen("Jitter_Duration")))
    198         {
    199             qoeMetrics.name[QoEMetricsType::JITTER_DURATION] = true;
    200             sptr = sptr + oscl_strlen("Jitter_Duration");
    201         }
    202         else if (!oscl_strncmp(sptr, "Decoded_Bytes",
    203                                oscl_strlen("Decoded_Bytes")))
    204         {
    205             qoeMetrics.name[QoEMetricsType::DECODED_BYTES] = true;
    206             sptr = sptr + oscl_strlen("Decoded_Bytes");
    207         }
    208         else
    209             return false;
    210 
    211         sptr = skip_whitespace_and_line_term(sptr, end_ptr);
    212         if (sptr > end_ptr)
    213             return false;
    214 
    215         if (!oscl_strncmp(sptr, ",", 1))
    216             sptr = sptr + 1;
    217         else if (!oscl_strncmp(sptr, "}", 1))
    218         {
    219             sptr = sptr + 1;
    220             break;
    221         }
    222     }
    223 
    224     if (sptr > end_ptr)
    225         return false;
    226 
    227     if (!oscl_strncmp(sptr, ";", 1))
    228         sptr = sptr + 1;
    229     else
    230         return false;
    231 
    232     if (!oscl_strncmp(sptr, rate.c_str(), rate.length()))
    233     {
    234         sptr = sptr + rate.length();
    235         if (!oscl_strncmp(sptr, "End", oscl_strlen("End")))
    236         {
    237             qoeMetrics.rateFmt = QoEMetricsType::END;
    238             qoeMetrics.rateEnd = 'E';
    239             sptr = sptr + oscl_strlen("End");
    240 
    241         }
    242         else
    243         {
    244             uint32 temp;
    245             eptr = sptr;        //get length of range digit
    246             for (; (*eptr != ';' && eptr < end_ptr); ++eptr);
    247 
    248             qoeMetrics.rateFmt = QoEMetricsType::VAL;
    249 
    250             if (PV_atoi(sptr, 'd', (int)(eptr  - sptr), temp))
    251             {
    252                 qoeMetrics.rateVal = temp;
    253                 sptr = eptr ;
    254             }
    255             else
    256                 return false;
    257         }
    258 
    259     }
    260     else
    261         return false;
    262 
    263     if (sptr == end_ptr) //end of line reached.
    264         return true;
    265 
    266     if (sptr > end_ptr)
    267         return false;
    268 
    269     if (!oscl_strncmp(sptr, ";", 1))
    270         sptr = sptr + 1;
    271     else
    272         return false;
    273     if (!oscl_strncmp(sptr, range.c_str(), range.length()))
    274     {
    275         eptr = sptr + range.length();
    276         for (; *eptr != ';' && eptr != end_ptr ; eptr++); // get length of range.
    277 
    278         if (!parseRtspRange((sptr + range.length()), (eptr - sptr - range.length()),
    279                             qoeMetrics.range))
    280             return false;
    281     }
    282 
    283     sptr = eptr;
    284     if (sptr == end_ptr)
    285         return true;    // end of line reached.
    286     else  //Parameter_Ext
    287     {
    288         sptr = eptr + 1;
    289         if (!oscl_strncmp(sptr, "On", oscl_strlen("On")))
    290         {
    291             qoeMetrics.paramExtStat = true;
    292             qoeMetrics.paramFmt = QoEMetricsType::STATUS;
    293         }
    294         else if (!oscl_strncmp(sptr, "Off", oscl_strlen("Off")))
    295         {
    296             qoeMetrics.paramExtStat = false;
    297             qoeMetrics.paramFmt = QoEMetricsType::STATUS;
    298         }
    299         else
    300         {
    301             uint32 len = OSCL_MIN((uint32)(eptr - sptr), oscl_strlen("."));
    302             if (oscl_strncmp(sptr, ".", len) == 0)  //if floating point number
    303             {
    304                 if (!PV_atof(sptr, (int)(eptr - sptr), qoeMetrics.paramExtFdigit))
    305                     return false;
    306                 qoeMetrics.paramFmt = QoEMetricsType::FDIGIT;
    307             }
    308             else                // hex digit
    309             {
    310                 uint32 temp;
    311                 if (PV_atoi(sptr, 'x', (int)(eptr - sptr), temp))
    312                 {
    313                     qoeMetrics.paramExtIdigit = temp;
    314                     qoeMetrics.paramFmt = QoEMetricsType::IDIGIT;
    315 
    316                 }
    317                 else
    318                     return false;
    319             }
    320 
    321         }
    322 
    323 
    324     }
    325 
    326     return true;
    327 
    328 }
    329 
    330 void pvSDPParserGetAssetInfoLanguageCode(uint16 langcode, char* LangCode)
    331 {
    332     //ISO-639-2/T 3-char Lang Code
    333     oscl_memset(LangCode, 0, 4);
    334     LangCode[0] = 0x60 + ((langcode >> 10) & 0x1F);
    335     LangCode[1] = 0x60 + ((langcode >> 5) & 0x1F);
    336     LangCode[2] = 0x60 + ((langcode) & 0x1F);
    337 }
    338 
    339 bool pvSDPParserParse3GPPAssetInfoLocation(AssetInfoType& ainfo,
    340         uint8* aBuf,
    341         uint32 aBufSize)
    342 {
    343     uint32 count = 0;
    344     uint16 lang = *aBuf++;
    345     lang = ((lang << 8) | (*aBuf++));
    346     count += 2;
    347     uint16 byteOrderMask = 0;
    348     byteOrderMask = *aBuf;
    349     byteOrderMask =
    350         ((byteOrderMask << 8) | (*(aBuf + 1)));
    351     if (byteOrderMask == BYTE_ORDER_MASK)
    352     {
    353         aBuf += 2;
    354         uint32 index = 0;
    355         uint8 firstbyte = aBuf[index];
    356         uint8 secondbyte = aBuf[index++];
    357         oscl_wchar wc = (uint16)(firstbyte << 8 | (uint16) secondbyte);
    358         bool nextChar = (wc == 0) ? false : true;
    359         while (nextChar && (index < aBufSize))
    360         {
    361             firstbyte = aBuf[index];
    362             secondbyte = aBuf[index++];
    363             wc = (uint16)(firstbyte << 8 | (uint16) secondbyte);
    364             nextChar = (wc == 0) ? false : true;
    365         }
    366         ainfo.iLocationStruct._location_name =
    367             (oscl_wchar*)(oscl_malloc(sizeof(oscl_wchar) * (index + 1)));
    368         if (ainfo.iLocationStruct._location_name == NULL) return false;
    369         oscl_memcpy(ainfo.iLocationStruct._location_name, aBuf, (index*2));
    370     }
    371     else
    372     {
    373         uint32 index = 0;
    374         bool nextChar = (aBuf[index] == 0) ? false : true;
    375         while (nextChar && (index < aBufSize))
    376         {
    377             index++;
    378             nextChar = (aBuf[index] == 0) ? false : true;
    379         }
    380         oscl_wchar* unicodeBuf = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * (index + 1));
    381         if (unicodeBuf == NULL) return false;
    382         oscl_UTF8ToUnicode((char*)aBuf,
    383                            index,
    384                            unicodeBuf,
    385                            index + 1);
    386         ainfo.iLocationStruct._location_name = unicodeBuf;
    387     }
    388     ainfo.iLocationStruct._role = *aBuf++;
    389     uint32 i;
    390     ainfo.iLocationStruct._longitude = 0;
    391     for (i = 0; i < 4; i++)
    392     {
    393         ainfo.iLocationStruct._longitude |= *aBuf++;
    394     }
    395     ainfo.iLocationStruct._latitude = 0;
    396     for (i = 0; i < 4; i++)
    397     {
    398         ainfo.iLocationStruct._latitude |= *aBuf++;
    399     }
    400     ainfo.iLocationStruct._altitude = 0;
    401     for (i = 0; i < 4; i++)
    402     {
    403         ainfo.iLocationStruct._altitude |= *aBuf++;
    404     }
    405     byteOrderMask = *aBuf;
    406     byteOrderMask =
    407         ((byteOrderMask << 8) | (*(aBuf + 1)));
    408     if (byteOrderMask == BYTE_ORDER_MASK)
    409     {
    410         aBuf += 2;
    411         uint32 index = 0;
    412         uint8 firstbyte = aBuf[index];
    413         uint8 secondbyte = aBuf[index++];
    414         oscl_wchar wc = (uint16)(firstbyte << 8 | (uint16) secondbyte);
    415         bool nextChar = (wc == 0) ? false : true;
    416         while (nextChar && (index < aBufSize))
    417         {
    418             firstbyte = aBuf[index];
    419             secondbyte = aBuf[index++];
    420             wc = (uint16)(firstbyte << 8 | (uint16) secondbyte);
    421             nextChar = (wc == 0) ? false : true;
    422         }
    423         ainfo.iLocationStruct._astronomical_body =
    424             (oscl_wchar*)(oscl_malloc(sizeof(oscl_wchar) * (index + 1)));
    425         if (ainfo.iLocationStruct._astronomical_body == NULL) return false;
    426         oscl_memcpy(ainfo.iLocationStruct._astronomical_body, aBuf, (index*2));
    427     }
    428     else
    429     {
    430         uint32 index = 0;
    431         bool nextChar = (aBuf[index] == 0) ? false : true;
    432         while (nextChar && (index < aBufSize))
    433         {
    434             index++;
    435             nextChar = (aBuf[index] == 0) ? false : true;
    436         }
    437         oscl_wchar* unicodeBuf = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * (index + 1));
    438         if (unicodeBuf == NULL) return false;
    439         oscl_UTF8ToUnicode((char*)aBuf,
    440                            index,
    441                            unicodeBuf,
    442                            index + 1);
    443         ainfo.iLocationStruct._astronomical_body = unicodeBuf;
    444     }
    445     byteOrderMask = *aBuf;
    446     byteOrderMask =
    447         ((byteOrderMask << 8) | (*(aBuf + 1)));
    448     if (byteOrderMask == BYTE_ORDER_MASK)
    449     {
    450         aBuf += 2;
    451         uint32 index = 0;
    452         uint8 firstbyte = aBuf[index];
    453         uint8 secondbyte = aBuf[index++];
    454         oscl_wchar wc = (uint16)(firstbyte << 8 | (uint16) secondbyte);
    455         bool nextChar = (wc == 0) ? false : true;
    456         while (nextChar && (index < aBufSize))
    457         {
    458             firstbyte = aBuf[index];
    459             secondbyte = aBuf[index++];
    460             wc = (uint16)(firstbyte << 8 | (uint16) secondbyte);
    461             nextChar = (wc == 0) ? false : true;
    462         }
    463         ainfo.iLocationStruct._additional_notes =
    464             (oscl_wchar*)(oscl_malloc(sizeof(oscl_wchar) * index));
    465         if (ainfo.iLocationStruct._additional_notes == NULL) return false;
    466         oscl_memcpy(ainfo.iLocationStruct._additional_notes, aBuf, (index*2));
    467     }
    468     else
    469     {
    470         uint32 index = 0;
    471         bool nextChar = (aBuf[index] == 0) ? false : true;
    472         while (nextChar && (index < aBufSize))
    473         {
    474             index++;
    475             nextChar = (aBuf[index] == 0) ? false : true;
    476         }
    477         oscl_wchar* unicodeBuf = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * (index + 1));
    478         if (unicodeBuf == NULL) return false;
    479         oscl_UTF8ToUnicode((char*)aBuf,
    480                            index,
    481                            unicodeBuf,
    482                            index + 1);
    483         ainfo.iLocationStruct._additional_notes = unicodeBuf;
    484     }
    485     return true;
    486 }
    487 
    488 
    489 bool parseAssetInfo(const char *sptr, const char *line_end_ptr, AssetInfoType &ainfo)
    490 {
    491     const char *eptr = sptr;
    492     int assetbox;
    493 
    494     while (eptr < line_end_ptr)
    495     {
    496         sptr = skip_whitespace(sptr, line_end_ptr);
    497         if (oscl_CIstrncmp(sptr, "{", 1))
    498             return false;
    499         sptr = sptr + 1;
    500         sptr = skip_whitespace(sptr, line_end_ptr);
    501         if (sptr > line_end_ptr)
    502             return false;
    503 
    504         if (!oscl_CIstrncmp(sptr, "url=", oscl_strlen("url=")))
    505         {
    506             sptr = sptr + oscl_strlen("url=");
    507             sptr = skip_whitespace(sptr, line_end_ptr);
    508             if (sptr > line_end_ptr)
    509                 return false;
    510             if (!oscl_CIstrncmp(sptr, "\"", 1))
    511             {
    512                 sptr = sptr + 1;
    513                 sptr = skip_whitespace(sptr, line_end_ptr);
    514                 if (sptr > line_end_ptr)
    515                     return false;
    516                 eptr = sptr;
    517 
    518                 for (; *eptr != '"'; ++eptr);
    519 
    520                 ainfo.URL.set((const char *)sptr, (eptr - sptr));
    521             }
    522             else
    523             {
    524                 eptr = sptr;
    525 
    526                 for (; *eptr != '}'; ++eptr);
    527 
    528                 ainfo.URL.set((const char *)sptr, (eptr - sptr));
    529             }
    530             return true;
    531 
    532         }
    533 
    534         if (!oscl_CIstrncmp(sptr, "Title=", oscl_strlen("Title=")))
    535         {
    536             sptr = sptr + oscl_strlen("Title=");
    537             assetbox = (int) AssetInfoType::TITLE;
    538             ainfo.oTitlePresent = true;
    539         }
    540         else if (!oscl_CIstrncmp(sptr, "Description=", oscl_strlen("Description=")))
    541         {
    542             sptr = sptr + oscl_strlen("Description=");
    543             assetbox = (int) AssetInfoType::DESCRIPTION;
    544             ainfo.oDescriptionPresent = true;
    545         }
    546         else if (!oscl_CIstrncmp(sptr, "Copyright=", oscl_strlen("Copyright=")))
    547         {
    548             sptr = sptr + oscl_strlen("Copyright=");
    549             assetbox = (int) AssetInfoType::COPYRIGHT;
    550             ainfo.oCopyRightPresent = true;
    551         }
    552         else if (!oscl_CIstrncmp(sptr, "Performer=", oscl_strlen("Performer=")))
    553         {
    554             sptr = sptr + oscl_strlen("Performer=");
    555             assetbox = (int) AssetInfoType::PERFORMER;
    556             ainfo.oPerformerPresent = true;
    557         }
    558         else if (!oscl_CIstrncmp(sptr, "Author=", oscl_strlen("Author=")))
    559         {
    560             sptr = sptr + oscl_strlen("Author=");
    561             assetbox = (int) AssetInfoType::AUTHOR;
    562             ainfo.oAuthorPresent = true;
    563         }
    564         else if (!oscl_CIstrncmp(sptr, "Genre=", oscl_strlen("Genre=")))
    565         {
    566             sptr = sptr + oscl_strlen("Genre=");
    567             assetbox = (int) AssetInfoType::GENRE;
    568             ainfo.oGenrePresent = true;
    569         }
    570         else if (!oscl_CIstrncmp(sptr, "Rating=", oscl_strlen("Rating=")))
    571         {
    572             sptr = sptr + oscl_strlen("Rating=");
    573             assetbox = (int) AssetInfoType::RATING;
    574             ainfo.oRatingPresent = true;
    575         }
    576         else if (!oscl_CIstrncmp(sptr, "Classification=", oscl_strlen("Classification=")))
    577         {
    578             sptr = sptr + oscl_strlen("Classification=");
    579             assetbox = (int) AssetInfoType::CLASSIFICATION;
    580             ainfo.oClassificationPresent = true;
    581         }
    582         else if (!oscl_CIstrncmp(sptr, "Keywords=", oscl_strlen("Keywords=")))
    583         {
    584             sptr = sptr + oscl_strlen("Keywords=");
    585             assetbox = (int) AssetInfoType::KEYWORDS;
    586             ainfo.oKeyWordsPresent = true;
    587         }
    588         else if (!oscl_CIstrncmp(sptr, "Location=", oscl_strlen("Location=")))
    589         {
    590             sptr = sptr + oscl_strlen("Location=");
    591             assetbox = (int) AssetInfoType::LOCATION;
    592             ainfo.oLocationPresent = true;
    593         }
    594         else if (!oscl_CIstrncmp(sptr, "Album=", oscl_strlen("Album=")))
    595         {
    596             sptr = sptr + oscl_strlen("Album=");
    597             assetbox = (int) AssetInfoType::ALBUM;
    598             ainfo.oAlbumPresent = true;
    599         }
    600         else if (!oscl_CIstrncmp(sptr, "RecordingYear=", oscl_strlen("RecordingYear=")))
    601         {
    602             sptr = sptr + oscl_strlen("RecordingYear=");
    603             assetbox = (int) AssetInfoType::RECORDINGYEAR;
    604             ainfo.oRecordingYearPresent = true;
    605         }
    606         else// if(!oscl_CIstrncmp(sptr, "asset-extention=", oscl_strlen("asset-extention=")))
    607         {//asset-extension ignore for now
    608             //sptr = sptr + oscl_strlen("asset-extention=");
    609             assetbox = (int) AssetInfoType::ASSET_EXTENTION;
    610             ainfo.oAssetExtensionPresent = true;
    611         }
    612 
    613         sptr = skip_whitespace(sptr, line_end_ptr);
    614         if (sptr > line_end_ptr)
    615             return false;
    616 
    617         for (eptr = sptr; *eptr != '}'; ++eptr)
    618         {
    619             if (eptr > line_end_ptr)
    620                 return false;
    621         }
    622 
    623         {
    624             //(here sptr is the complete value of base64 encoded metadata)
    625             uint8* inBuf = (uint8*)sptr;
    626             //(length of base64 encode metadata value)
    627             uint32 inBufLen = (eptr - sptr);
    628             //(string to collect the base64 decoded data)
    629             uint8* outBuf = (uint8*)oscl_malloc(inBufLen);
    630             if (outBuf != NULL)
    631             {
    632                 //(max length of the base64 decoded data)
    633                 uint32 maxoutBuflen = inBufLen;
    634                 uint32 outBuflen = 0;
    635                 sdp_decodebase64(inBuf, inBufLen, outBuf, outBuflen, maxoutBuflen);
    636                 //4 bytes size, 4 bytes fourcc, 4 bytes flags
    637                 uint32 assetinfoatomoffset = 12;
    638                 if (outBuflen > assetinfoatomoffset)
    639                 {
    640                     uint8* buf = outBuf + assetinfoatomoffset;
    641                     if ((assetbox == AssetInfoType::TITLE) ||
    642                             (assetbox == AssetInfoType::DESCRIPTION) ||
    643                             (assetbox == AssetInfoType::COPYRIGHT) ||
    644                             (assetbox == AssetInfoType::PERFORMER) ||
    645                             (assetbox == AssetInfoType::AUTHOR) ||
    646                             (assetbox == AssetInfoType::GENRE) ||
    647                             (assetbox == AssetInfoType::ALBUM) ||
    648                             (assetbox == AssetInfoType::RATING) ||
    649                             (assetbox == AssetInfoType::CLASSIFICATION))
    650                     {
    651                         char rating_entity[21];
    652                         char rating_criteria[21];
    653                         if (assetbox == AssetInfoType::RATING)
    654                         {
    655                             oscl_snprintf(rating_entity,
    656                                           oscl_strlen(PVSDPMETADATA_RATING_ENTITY) + 4,
    657                                           "%s%s",
    658                                           PVSDPMETADATA_RATING_ENTITY, buf);
    659                             buf += 4;
    660                             rating_entity[20] = '\0';
    661                             oscl_snprintf(rating_criteria,
    662                                           oscl_strlen(PVSDPMETADATA_RATING_CRITERIA) + 4,
    663                                           "%s%s",
    664                                           PVSDPMETADATA_RATING_CRITERIA, buf);
    665                             buf += 4;
    666                             rating_criteria[20] = '\0';
    667                         }
    668                         char classification_entity[26];
    669                         char classification_table[26];
    670                         if (assetbox == AssetInfoType::CLASSIFICATION)
    671                         {
    672                             oscl_snprintf(classification_entity,
    673                                           oscl_strlen(PVSDPMETADATA_CLASSIFICATION_ENTITY) + 4,
    674                                           "%s%s",
    675                                           PVSDPMETADATA_CLASSIFICATION_ENTITY, buf);
    676                             buf += 4;
    677                             classification_entity[25] = '\0';
    678                             oscl_snprintf(classification_table,
    679                                           oscl_strlen(PVSDPMETADATA_CLASSFICATION_TABLE) + 2,
    680                                           "%s%s",
    681                                           PVSDPMETADATA_CLASSFICATION_TABLE, buf);
    682                             buf += 2;
    683                             classification_table[25] = '\0';
    684                         }
    685                         uint16 lang = *buf++;
    686                         lang = ((lang << 8) | (*buf++));
    687                         char LangCode[4];
    688                         pvSDPParserGetAssetInfoLanguageCode(lang, LangCode);
    689                         char lang_param[21];
    690                         oscl_snprintf(lang_param,
    691                                       oscl_strlen(PVSDPMETADATA_LANG_CODE) + 4,
    692                                       "%s%s", PVSDPMETADATA_LANG_CODE, LangCode);
    693                         lang_param[20] = '\0';
    694                         uint16 byteOrderMask = *buf;
    695                         byteOrderMask =
    696                             ((byteOrderMask << 8) | (*(buf + 1)));
    697                         if (byteOrderMask == BYTE_ORDER_MASK)
    698                         {
    699                             buf += 2;
    700                             OsclBinIStreamBigEndian datastream;
    701                             datastream.Attach((void *)(buf), (outBuflen - assetinfoatomoffset - 2));
    702                             //(string to collect the utf8 data)
    703                             uint8* utf8Buf = (uint8*)oscl_malloc(inBufLen);
    704                             oscl_memset(utf8Buf, 0, inBufLen);
    705                             int32 unicodebuflen = (int32)((outBuflen - assetinfoatomoffset - 2) / 2);
    706                             oscl_wchar* unicodeBuf = (oscl_wchar*)oscl_malloc((unicodebuflen + 1) * sizeof(oscl_wchar));
    707                             oscl_memset(unicodeBuf, 0, (unicodebuflen + 1)*sizeof(oscl_wchar));
    708                             for (int32 i = 0; i < unicodebuflen; i++)
    709                             {
    710                                 uint16 temp = 0;
    711                                 datastream >> temp;
    712                                 unicodeBuf[i] = (uint16)(temp);
    713                             }
    714                             oscl_UnicodeToUTF8(unicodeBuf,
    715                                                unicodebuflen,
    716                                                (char*)utf8Buf,
    717                                                inBufLen);
    718                             ainfo.Box[assetbox].set((const char *)(utf8Buf),
    719                                                     oscl_strlen((const char*)utf8Buf));
    720                             oscl_free(utf8Buf);
    721                             oscl_free(unicodeBuf);
    722                         }
    723                         else
    724                         {
    725                             ainfo.Box[assetbox].set((const char *)(buf),
    726                                                     (outBuflen - assetinfoatomoffset));
    727                         }
    728                         ainfo.Box[assetbox] += lang_param;
    729                         if (assetbox == AssetInfoType::RATING)
    730                         {
    731                             ainfo.Box[assetbox] += rating_entity;
    732                             ainfo.Box[assetbox] += rating_criteria;
    733                         }
    734                         else if (assetbox == AssetInfoType::CLASSIFICATION)
    735                         {
    736                             ainfo.Box[assetbox] += classification_entity;
    737                             ainfo.Box[assetbox] += classification_table;
    738                         }
    739                     }
    740                     else if (assetbox == AssetInfoType::RECORDINGYEAR)
    741                     {
    742                         ainfo.iRecordingYear = 0;
    743                         ainfo.iRecordingYear = *buf++;
    744                         ainfo.iRecordingYear = ((ainfo.iRecordingYear << 8) | (*buf++));
    745                     }
    746                     else if (assetbox == AssetInfoType::KEYWORDS)
    747                     {
    748                         uint16 lang = *buf++;
    749                         lang = ((lang << 8) | (*buf++));
    750                         char LangCode[4];
    751                         pvSDPParserGetAssetInfoLanguageCode(lang, LangCode);
    752                         char lang_param[21];
    753                         oscl_snprintf(lang_param,
    754                                       oscl_strlen(PVSDPMETADATA_LANG_CODE) + 4,
    755                                       "%s%s", PVSDPMETADATA_LANG_CODE, LangCode);
    756                         lang_param[20] = '\0';
    757                         ainfo.iNumKeyWords = (uint32)(*buf++);
    758                         for (uint32 i = 0; i < ainfo.iNumKeyWords; i++)
    759                         {
    760                             OSCL_HeapString<OsclMemAllocator> keyWordString;
    761                             uint32 keywordsize = (uint32)(*buf++);
    762                             uint16 byteOrderMask = *buf;
    763                             byteOrderMask =
    764                                 ((byteOrderMask << 8) | (*(buf + 1)));
    765                             if (byteOrderMask == BYTE_ORDER_MASK)
    766                             {
    767                                 buf += 2;
    768                                 keywordsize -= 2;
    769                                 OsclBinIStreamBigEndian datastream;
    770                                 datastream.Attach((void *)(buf), keywordsize);
    771                                 //(string to collect the utf8 data)
    772                                 uint8* utf8Buf = (uint8*)oscl_malloc(keywordsize);
    773                                 oscl_memset(utf8Buf, 0, keywordsize);
    774                                 int32 unicodebuflen = (int32)((keywordsize) / 2);
    775                                 oscl_wchar* unicodeBuf = (oscl_wchar*)oscl_malloc((unicodebuflen + 1) * sizeof(oscl_wchar));
    776                                 oscl_memset(unicodeBuf, 0, (unicodebuflen + 1)*sizeof(oscl_wchar));
    777                                 for (int32 i = 0; i < unicodebuflen; i++)
    778                                 {
    779                                     uint16 temp = 0;
    780                                     datastream >> temp;
    781                                     unicodeBuf[i] = (uint16)(temp);
    782                                 }
    783                                 oscl_UnicodeToUTF8(unicodeBuf,
    784                                                    unicodebuflen,
    785                                                    (char*)utf8Buf,
    786                                                    inBufLen);
    787                                 keyWordString.set((const char *)(utf8Buf),
    788                                                   oscl_strlen((const char*)utf8Buf));
    789                                 oscl_free(utf8Buf);
    790                                 oscl_free(unicodeBuf);
    791                                 buf += keywordsize;
    792                             }
    793                             else
    794                             {
    795                                 keyWordString.set((const char *)(buf), keywordsize);
    796                                 buf += keywordsize;
    797                             }
    798                             keyWordString += lang_param;
    799                             ainfo.KeyWords[i] = keyWordString;
    800                         }
    801                     }
    802                     else if (assetbox == AssetInfoType::LOCATION)
    803                     {
    804                         if (pvSDPParserParse3GPPAssetInfoLocation(ainfo, buf, outBuflen) != true)
    805                         {
    806                             return false;
    807                         }
    808                     }
    809                     else
    810                     {
    811                         ainfo.Box[assetbox].set((const char *)(buf),
    812                                                 (outBuflen - assetinfoatomoffset));
    813                     }
    814                 }
    815                 oscl_free(outBuf);
    816             }
    817         }
    818         eptr = eptr + 1;
    819         sptr = eptr + 1;
    820     }
    821 
    822     return true;
    823 }
    824 
    825 
    826