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