• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_next_line(const char * start_ptr,const char * end_ptr,const char * & line_start,const char * & line_end)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 
sdp_decodebase64(uint8 * aInBuf,uint32 aInBufLen,uint8 * aOutBuf,uint32 & aOutBufLen,uint32 aMaxOutBufLen)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 
parseQoEMetrics(const char * start_ptr,const char * end_ptr,QoEMetricsType & qoeMetrics)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 
pvSDPParserGetAssetInfoLanguageCode(uint16 langcode,char * LangCode)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 
pvSDPParserParse3GPPAssetInfoLocation(AssetInfoType & ainfo,uint8 * aBuf,uint32 aBufSize)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 
parseAssetInfo(const char * sptr,const char * line_end_ptr,AssetInfoType & ainfo)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