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 #include "oscl_mem_basic_functions.h"
19 #include "oscl_snprintf.h"
20 #include "oscl_string_utils.h"
21 #include "oscl_str_ptr_len.h"
22 #include "oscl_string.h"
23 #include "rtsp_time_formats.h"
24 #include "rtsp_range_utils.h"
25
26
27 #include "oscl_dll.h"
28 OSCL_DLL_ENTRY_POINT_DEFAULT()
29
30
31 // don't make the max int size less than 6 -- it is
32 // used to size certain arrays below that need at least 6 characters
33 static const int MAX_RANGE_INT_SIZE = 10;
34
35 // keep the next two constants in sync. The max range float
36 // size should be the number of digits plus the decimal point
37 static const int MAX_RANGE_FLOAT_SIZE = 7;
38 static const char RANGE_FLOAT_FORMAT[] = "%0.6f";
39
parse_range_integer(const char * start,const char * end,int max_digits,char * sep,uint32 & value)40 OSCL_EXPORT_REF const char * parse_range_integer(const char *start, const char *end,
41 int max_digits, char *sep, uint32& value)
42 {
43 const char *sptr, *eptr;
44 const char *endpoint;
45
46 if (max_digits > 0 && ((end - start) > max_digits))
47 {
48 endpoint = start + max_digits;
49 }
50 else
51 {
52 endpoint = end;
53 }
54
55 sptr = start;
56
57 if (sep)
58 {
59 for (eptr = sptr; eptr < endpoint &&
60 *eptr != *sep ; ++eptr);
61 }
62 else
63 {
64 eptr = endpoint;
65 }
66
67 // get the hours
68 uint32 tmp;
69 if (PV_atoi(sptr, 'd', eptr - sptr, tmp) == false)
70 {
71 return NULL;
72 }
73
74 value = tmp;
75 return eptr;
76
77 }
78
parse_smpte_format(const char * start_ptr,const char * end_ptr,RtspRangeType::RtspRangeFormat format,SmpteTimeFormat & smpte_range)79 OSCL_EXPORT_REF bool parse_smpte_format(const char* start_ptr, const char *end_ptr,
80 RtspRangeType::RtspRangeFormat format,
81 SmpteTimeFormat& smpte_range)
82 {
83
84 // get required HH:MM:SS values
85 const char *sptr;
86
87 sptr = start_ptr;
88 uint32 tmp;
89 char sep;
90
91 sep = ':';
92 sptr = parse_range_integer(sptr, end_ptr,
93 2, &sep, tmp);
94
95 if (!sptr || *sptr != ':')
96 {
97 return false;
98 }
99
100 smpte_range.hours = (uint8)tmp;
101
102 // get the minutes
103 sptr = parse_range_integer(sptr + 1, end_ptr,
104 2, &sep, tmp);
105
106 if (!sptr || *sptr != ':')
107 {
108 return false;
109 }
110
111 if (tmp > 59)
112 {
113 return false;
114 }
115
116 smpte_range.minutes = (uint8)tmp;
117
118 // get the seconds
119 sptr = parse_range_integer(sptr + 1, end_ptr,
120 2, &sep, tmp);
121
122 if (!sptr)
123 {
124 return false;
125 }
126
127 if (tmp > 59)
128 {
129 return false;
130 }
131
132 smpte_range.seconds = (uint8)tmp;
133
134 // now see if there there are any optional fields
135 if (*sptr == ':')
136 {
137 // get the number of frames
138 sep = '.';
139 sptr = parse_range_integer(sptr + 1, end_ptr,
140 2, &sep, tmp);
141
142 if (!sptr)
143 {
144 return false;
145 }
146
147 if (format == RtspRangeType::SMPTE_25_RANGE &&
148 tmp > 25)
149 {
150 return false;
151 }
152 else if (tmp > 30)
153 {
154 return false;
155 }
156
157 smpte_range.frames = (uint8)tmp;
158
159 // now check for optional subframes
160 if (*sptr == '.')
161 {
162 // get the number of subframes
163 sptr = parse_range_integer(sptr + 1, end_ptr,
164 2, NULL, tmp);
165
166 if (!sptr)
167 {
168 return false;
169 }
170
171 if (tmp > 99)
172 {
173 return false;
174 }
175
176 smpte_range.subframes = (uint8)tmp;
177 }
178 else
179 {
180 smpte_range.subframes = 0;
181 }
182
183 }
184 else
185 {
186 smpte_range.frames = 0;
187 smpte_range.subframes = 0;
188 }
189
190 return true;
191 }
192
parse_npt_format(const char * start_ptr,const char * end_ptr,NptTimeFormat & npt_range)193 OSCL_EXPORT_REF bool parse_npt_format(const char* start_ptr, const char *end_ptr,
194 NptTimeFormat& npt_range)
195 {
196
197 // get required HH:MM:SS values
198 const char *sptr, *eptr;
199 uint32 tmp;
200
201 sptr = start_ptr;
202
203 StrPtrLen now_str("now");
204 if (!oscl_strncmp(sptr, now_str.c_str(), now_str.length()))
205 {
206 // this is the "now" keyword
207 npt_range.npt_format = NptTimeFormat::NOW;
208 return true;
209 }
210
211 // see if the format contains a ':' separator character
212 for (eptr = sptr; eptr < end_ptr && *eptr != ':'; ++eptr);
213
214 if (*eptr == ':')
215 {
216 // this is the npt-hhmmss format
217
218 char sep = ':';
219 // get the number of hours
220 sptr = parse_range_integer(sptr, eptr,
221 0, &sep, tmp);
222
223 if (!sptr)
224 {
225 return false;
226 }
227
228 npt_range.npt_format = NptTimeFormat::NPT_HHMMSS;
229 npt_range.npt_hhmmss.hours = tmp;
230
231
232 // get the number of minutes
233 sptr = parse_range_integer(sptr + 1, end_ptr,
234 2, &sep, tmp);
235
236 if (!sptr || *sptr != ':')
237 {
238 return false;
239 }
240
241 if (tmp > 59)
242 {
243 return false;
244 }
245
246 npt_range.npt_hhmmss.min = (uint8)tmp;
247
248
249 sep = '.';
250 // get the number of seconds
251 sptr = parse_range_integer(sptr + 1, end_ptr,
252 2, &sep, tmp);
253
254 if (!sptr)
255 {
256 return false;
257 }
258
259 if (tmp > 59)
260 {
261 return false;
262 }
263
264 npt_range.npt_hhmmss.sec = (uint8)tmp;
265
266 npt_range.npt_hhmmss.frac_sec = 0;
267 // determine if the fractional seconds exists
268 if (*sptr == '.')
269 {
270 // get the fractional seconds
271 const int MAX_TMP_BUFSIZE = 12;
272 char tmpbuf[MAX_TMP_BUFSIZE];
273 int copy_size;
274
275 eptr = skip_to_whitespace(sptr, end_ptr);
276
277 copy_size = eptr - sptr;
278 if (copy_size > MAX_TMP_BUFSIZE - 1)
279 {
280 copy_size = MAX_TMP_BUFSIZE - 1;
281 }
282
283 oscl_strncpy(tmpbuf, sptr, copy_size);
284
285 tmpbuf[copy_size] = '\0';
286
287 if (!PV_atof(tmpbuf, npt_range.npt_hhmmss.frac_sec))
288 return false;
289
290 }
291
292 } // end if the format is NPT_HHMMSS
293
294 else
295 {
296
297 char sep = '.';
298 // this is the NPT_SEC format
299 npt_range.npt_format = NptTimeFormat::NPT_SEC;
300
301 // get the number of seconds
302 sptr = parse_range_integer(sptr, eptr,
303 0, &sep, tmp);
304
305 if (!sptr)
306 {
307 return false;
308 }
309
310 npt_range.npt_sec.sec = tmp;
311
312 npt_range.npt_sec.milli_sec = 0;
313 if (*sptr == '.')
314 {
315 // there is an optional fractional seconds field
316
317 // get the fractional seconds
318 const int MAX_TMP_BUFSIZE = 12;
319 char tmpbuf[MAX_TMP_BUFSIZE];
320 int copy_size;
321
322 eptr = skip_to_whitespace(sptr, end_ptr);
323
324 copy_size = eptr - sptr;
325
326 if (copy_size > MAX_TMP_BUFSIZE - 1)
327 {
328 copy_size = MAX_TMP_BUFSIZE - 1;
329 }
330
331 oscl_strncpy(tmpbuf, sptr, copy_size);
332
333
334 tmpbuf[copy_size] = '\0';
335
336 OsclFloat tmp_fnum;
337 if (!PV_atof(tmpbuf, tmp_fnum))
338 return false;
339 npt_range.npt_sec.milli_sec = (uint32)(1000.0 * tmp_fnum + 0.5);
340 }
341
342 } // end if the format is NPT_SEC
343
344 return true;
345 }
346
347
parse_abs_format(const char * start_ptr,const char * end_ptr,AbsTimeFormat & abs_range)348 OSCL_EXPORT_REF bool parse_abs_format(const char* start_ptr, const char *end_ptr,
349 AbsTimeFormat& abs_range)
350 {
351
352 // get format YYYYMMDDT
353 const char *sptr, *eptr;
354 char sep;
355 uint32 tmp;
356
357 sptr = start_ptr;
358
359 // check if the ninth character is a "T"
360 eptr = sptr + 8;
361
362 sep = 'T';
363 if (eptr >= end_ptr || *eptr != sep)
364 {
365 return false;
366 }
367
368 sptr = parse_range_integer(sptr, eptr,
369 4, &sep, tmp);
370
371 if (! sptr || tmp > 9999)
372 {
373 return false;
374 }
375
376 abs_range.year = (uint16)tmp;
377
378 // get the month
379 sptr = parse_range_integer(sptr, eptr,
380 2, &sep, tmp);
381
382 if (! sptr || tmp == 0 || tmp > 12)
383 {
384 return false;
385 }
386
387 abs_range.month = (uint8)tmp;
388
389 // get the day
390 sptr = parse_range_integer(sptr, eptr,
391 2, &sep, tmp);
392
393 if (! sptr || tmp == 0 || tmp > 31)
394 {
395 return false;
396 }
397
398 abs_range.day = (uint8)tmp;
399
400
401 sptr = eptr + 1;
402 eptr = sptr + 6;
403
404 if (eptr >= end_ptr || (*eptr != 'Z' && *eptr != '.'))
405 {
406 return false;
407 }
408
409 // get the hours
410 sptr = parse_range_integer(sptr, eptr,
411 2, NULL, tmp);
412
413 if (! sptr || tmp > 23)
414 {
415 return false;
416 }
417
418 abs_range.hours = (uint8)tmp;
419
420 // get the minutes
421 sptr = parse_range_integer(sptr, eptr,
422 2, NULL, tmp);
423
424 if (! sptr || tmp > 59)
425 {
426 return false;
427 }
428
429 abs_range.min = (uint8)tmp;
430
431 // get the number of seconds
432 sptr = parse_range_integer(sptr, eptr,
433 2, NULL, tmp);
434
435 if (! sptr || tmp > 59)
436 {
437 return false;
438 }
439
440 abs_range.sec = (uint8)tmp;
441
442 abs_range.frac_sec = 0;
443
444 if (*eptr == '.')
445 {
446 // get the fractional seconds
447 // get the fractional seconds
448 const int MAX_TMP_BUFSIZE = 12;
449 char tmpbuf[MAX_TMP_BUFSIZE];
450 int copy_size;
451
452 sptr = eptr;
453
454 for (eptr = sptr; eptr < end_ptr && *eptr != 'Z';
455 ++eptr);
456
457 if (*eptr != 'Z')
458 {
459 return false;
460 }
461
462 copy_size = eptr - sptr;
463 if (copy_size > MAX_TMP_BUFSIZE - 1)
464 {
465 copy_size = MAX_TMP_BUFSIZE - 1;
466 }
467
468 oscl_strncpy(tmpbuf, sptr, copy_size);
469
470 tmpbuf[copy_size] = '\0';
471
472 if (!PV_atof(tmpbuf, abs_range.frac_sec))
473 return false;
474
475 }
476
477 return true;
478 }
479
480
parseRtspRange(const char * rangeString,int length,RtspRangeType & range)481 OSCL_EXPORT_REF bool parseRtspRange(const char *rangeString, int length, RtspRangeType& range)
482 {
483 const char *end = rangeString + length;
484
485 const char* sptr, *eptr;
486
487 // initialize range to invalid format
488 range.format = RtspRangeType::INVALID_RANGE;
489
490 // find the first word before the "="
491 sptr = skip_whitespace_and_line_term(rangeString, end);
492 if (sptr >= end)
493 {
494 return false;
495 }
496
497 for (eptr = sptr; eptr < end &&
498 (*eptr != '=' && *eptr != ':' && *eptr != ' ' && *eptr != '\t');
499 ++eptr);
500
501
502 StrPtrLen smpte_type("smpte");
503 StrPtrLen smpte25_type("smpte-25");
504 StrPtrLen smpte30_type("smpte-30-drop");
505 StrPtrLen npt_type("npt");
506 StrPtrLen abs_type("clock");
507 //#ifdef RTSP_PLAYLIST_SUPPORT
508 StrPtrLen playlist_play_time_type("playlist_play_time");
509 //#endif //#ifdef RTSP_PLAYLIST_SUPPORT
510
511 if (!oscl_strncmp(sptr, smpte_type.c_str(), eptr - sptr) ||
512 !oscl_strncmp(sptr, smpte25_type.c_str(), eptr - sptr) ||
513 !oscl_strncmp(sptr, smpte30_type.c_str(), eptr - sptr))
514 {
515 // Parsing one of the SMPTE time formats
516
517 // save the exact format temporarily
518 RtspRangeType::RtspRangeFormat tmp_format;
519 if (!oscl_strncmp(sptr, smpte30_type.c_str(), smpte30_type.length()))
520 {
521 tmp_format = RtspRangeType::SMPTE_30_RANGE;
522 }
523 else if (!oscl_strncmp(sptr, smpte25_type.c_str(), smpte25_type.length()))
524 {
525 tmp_format = RtspRangeType::SMPTE_25_RANGE;
526 }
527 else
528 {
529 tmp_format = RtspRangeType::SMPTE_RANGE;
530 }
531
532 // skip ahead to beyond the "="
533 if (*eptr != '=')
534 {
535 for (; eptr < end && *eptr != '='; ++eptr);
536 }
537
538 sptr = skip_whitespace(eptr + 1, end);
539 if (sptr >= end)
540 {
541 return false;
542 }
543
544 // find the start/end separator
545 for (eptr = sptr; eptr < end &&
546 (*eptr != '-'); ++eptr);
547
548 if (*eptr != '-')
549 {
550 return false;
551 }
552
553 range.start_is_set = false;
554 if (eptr > sptr)
555 {
556 // there is a start time
557
558 if (parse_smpte_format(sptr, eptr, tmp_format, range.smpte_start) == false)
559 {
560 return false;
561 }
562
563 // now set the appropriate flags
564 range.start_is_set = true;
565 }
566
567 // see if there is a stop time
568 sptr = skip_whitespace_and_line_term(eptr + 1, end);
569 range.end_is_set = false;
570 if (sptr < end)
571 {
572 // there is a stop time specification
573 eptr = skip_to_whitespace(sptr, end);
574
575 if (parse_smpte_format(sptr, eptr, tmp_format, range.smpte_end)
576 == false)
577 {
578 return false;
579 }
580
581 // now set the appropriate flags
582 range.end_is_set = true;
583 }
584
585 // now set the appropriate range format
586 range.format = tmp_format;
587
588 } // end if this is an SMPTE time format
589
590 else if (!oscl_strncmp(sptr, npt_type.c_str(), eptr - sptr))
591 {
592
593 // skip ahead to beyond the "=" or ":"
594 if (*eptr != '=')
595 {
596 for (; eptr < end && *eptr != '=' && *eptr != ':'; ++eptr);
597 }
598
599 sptr = skip_whitespace(eptr + 1, end);
600 if (sptr >= end)
601 {
602 return false;
603 }
604
605 // find the start/end separator
606 for (eptr = sptr; eptr < end &&
607 (*eptr != '-'); ++eptr);
608
609 if (*eptr != '-')
610 {
611 return false;
612 }
613
614 range.start_is_set = false;
615 if (eptr > sptr)
616 {
617 // there is a start time
618 if (parse_npt_format(sptr, eptr, range.npt_start) == false)
619 {
620 return false;
621 }
622
623 // now set the appropriate flags
624 range.start_is_set = true;
625
626 }
627
628 // see if there is a stop time
629 range.end_is_set = false;
630 sptr = skip_whitespace_and_line_term(eptr + 1, end);
631 if (sptr < end)
632 {
633 // there is a stop time specification
634 eptr = skip_to_whitespace(sptr, end);
635
636 if (parse_npt_format(sptr, eptr, range.npt_end)
637 == false)
638 {
639 return false;
640 }
641
642 // now set the appropriate flags
643 range.end_is_set = true;
644 }
645
646 // now set the appropriate range format
647 range.format = RtspRangeType::NPT_RANGE;
648
649 } // end if this is an NPT time format
650
651 else if (!oscl_strncmp(sptr, abs_type.c_str(), eptr - sptr))
652 {
653
654
655 // skip ahead to beyond the "="
656 if (*eptr != '=')
657 {
658 for (; eptr < end && *eptr != '='; ++eptr);
659 }
660
661 sptr = skip_whitespace(eptr + 1, end);
662 if (sptr >= end)
663 {
664 return false;
665 }
666
667 // find the start/end separator
668 for (eptr = sptr; eptr < end &&
669 (*eptr != '-'); ++eptr);
670
671 if (*eptr != '-')
672 {
673 return false;
674 }
675
676 range.start_is_set = false;
677 if (eptr > sptr)
678 {
679 // there is a start time
680 if (parse_abs_format(sptr, eptr, range.abs_start) == false)
681 {
682 return false;
683 }
684
685 // now set the appropriate flags
686 range.start_is_set = true;
687
688 }
689
690 // see if there is a stop time
691 sptr = skip_whitespace_and_line_term(eptr + 1, end);
692 range.end_is_set = true;
693 if (sptr < end)
694 {
695 // there is a stop time specification
696 eptr = skip_to_whitespace(sptr, end);
697
698 if (parse_abs_format(sptr, eptr, range.abs_end)
699 == false)
700 {
701 return false;
702 }
703
704 // now set the appropriate flags
705 range.end_is_set = true;
706 }
707
708 // now set the appropriate range format
709 range.format = RtspRangeType::ABS_RANGE;
710
711 } // end if this is an ABS time format
712 //#ifdef RTSP_PLAYLIST_SUPPORT
713 // for Range:playlist_play_time=<URN,clipIndex,clipOffset>
714 //playlist_play_time=</public/playlist/va_playlists/test.ply,3,0.0>;npt=194.81542
715 else if (!oscl_strncmp(sptr, playlist_play_time_type.c_str(), eptr - sptr))
716 {
717 // store the whole string since we may not need the parsed version of things
718 //oscl_memcpy(range.iPlaylistPlayStr,rangeString,length);
719 //range.iPlaylistPlayStr[length] = '\0';
720
721 range.format = RtspRangeType::PLAYLIST_TIME_RANGE;
722 range.start_is_set = range.end_is_set = false;
723
724 // now set the appropriate flags
725 range.start_is_set = true;
726
727 // skip ahead to beyond the "="
728 if (*eptr != '=')
729 {
730 for (; eptr < end && *eptr != '='; ++eptr);
731 }
732
733 sptr = skip_whitespace(eptr + 1, end);
734 if (sptr >= end)
735 {
736 return false;
737 }
738
739 // next should be the opening "<"
740 // skip ahead to beyond the "<"
741 if (*eptr != '<')
742 {
743 for (; eptr < end && *eptr != '<'; ++eptr);
744 }
745
746 sptr = skip_whitespace(eptr + 1, end);
747 if (sptr >= end)
748 {
749 return false;
750 }
751
752 // find the comma separator
753 for (eptr = sptr; eptr < end &&
754 (*eptr != ','); ++eptr);
755
756 if (*eptr != ',')
757 {
758 return false;
759 }
760
761 // first the urn
762 if (eptr > sptr)
763 {
764 // there is a urn
765 if (oscl_memcpy(range.iPlaylistUrl, sptr, eptr - sptr) == false)
766 {
767 return false;
768 }
769 //range.iUrn[(eptr-sptr)+1] = '\0';
770 range.iPlaylistUrl[eptr-sptr] = '\0';
771 }
772
773 // now the clipIndex
774 sptr = skip_whitespace(eptr + 1, end);
775 if (sptr >= end)
776 {
777 return false;
778 }
779
780 // find the next comma separator
781 for (eptr = sptr; eptr < end &&
782 (*eptr != ','); ++eptr);
783
784 if (*eptr != ',')
785 {
786 return false;
787 }
788
789 // now the clipIndex
790 if (eptr > sptr)
791 {
792 // there is a clipIndex
793 uint32 tmp;
794 if (PV_atoi(sptr, 'd', eptr - sptr, tmp) == false)
795 {
796 return false;
797 }
798 range.playlist_start.iClipIndex = (int32)tmp;
799 }
800
801 // now the clipOffset
802 sptr = skip_whitespace(eptr + 1, end);
803 if (sptr >= end)
804 {
805 return false;
806 }
807
808 // find the final '>' separator or the final possible '.' in offset
809 //<sec>.<frac>
810 for (eptr = sptr; eptr < end &&
811 (*eptr != '>') && (*eptr != '.'); ++eptr);
812
813 if (eptr >= end)
814 {
815 return false;
816 }
817
818 // @todo ignore the factional part for now
819 // now the clipOffset
820 if (eptr > sptr)
821 {
822 // there is a clipOffset
823 uint32 tmp;
824 if (PV_atoi(sptr, 'd', eptr - sptr, tmp) == false)
825 {
826 return false;
827 }
828 range.playlist_start.sec = (int32)tmp;
829
830 {
831 range.playlist_start.milli_sec = 0;
832 if (*eptr == '.')
833 {
834 // there is an optional fractional seconds field
835
836 // get the fractional seconds
837 const int MAX_TMP_BUFSIZE = 12;
838 char tmpbuf[MAX_TMP_BUFSIZE];
839 int copy_size;
840
841 eptr = skip_to_whitespace(sptr, end);
842
843 copy_size = eptr - sptr;
844
845 if (copy_size > MAX_TMP_BUFSIZE - 1)
846 {
847 copy_size = MAX_TMP_BUFSIZE - 1;
848 }
849
850 oscl_strncpy(tmpbuf, sptr, copy_size);
851
852
853 tmpbuf[copy_size] = '\0';
854
855 OsclFloat tmp_fnum;
856 if (!PV_atof(tmpbuf, tmp_fnum))
857 return false;
858 range.playlist_start.milli_sec = (uint32)(1000.0 * tmp_fnum + 0.5);
859 }
860 }
861 }
862 } // end if this is a playlist_play_time format, for response to playlist_play commands
863 //#endif //#ifdef RTSP_PLAYLIST_SUPPORT
864 else
865 {
866 /*Unsupported time format*/
867 range.format = RtspRangeType::UNKNOWN_RANGE;
868 range.start_is_set = false;
869 range.end_is_set = false;
870 return false;
871 }
872
873 return true;
874 }
875
estimate_SDP_string_len(const NptTimeFormat & npt_range)876 OSCL_EXPORT_REF int estimate_SDP_string_len(const NptTimeFormat& npt_range)
877 {
878 int total_len = 0;
879
880
881 switch (npt_range.npt_format)
882 {
883 case NptTimeFormat::NOW:
884 total_len += 3; // enough for "now"
885 break;
886
887 case NptTimeFormat::NPT_SEC:
888 // compute the size for the sec field
889 if (npt_range.npt_sec.sec < 1000)
890 {
891 total_len += 3; // enough for at most 3 digits
892 }
893 else if (npt_range.npt_sec.sec < 1000000)
894 {
895 total_len += 6; // enough for 6 digits
896 }
897 else
898 {
899 total_len += 10; // enough for MAX_INT of uint32
900 }
901
902 if (npt_range.npt_sec.milli_sec > 0.0)
903 {
904 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits
905 }
906 break;
907
908 case NptTimeFormat::NPT_HHMMSS:
909 if (npt_range.npt_hhmmss.hours < 1000)
910 {
911 total_len += 3; // enough for at most 3 digits
912 }
913 else if (npt_range.npt_hhmmss.hours < 1000000)
914 {
915 total_len += 6; // enough for 6 digits
916 }
917 else
918 {
919 total_len += 10; // enough for MAX_INT of uint32
920 }
921
922 total_len += 6; // enough for ":MM:SS"
923
924 if (npt_range.npt_hhmmss.frac_sec > 0.0)
925 {
926 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits
927 }
928 break;
929 }
930
931 return total_len;
932 }
933
934
estimate_SDP_string_len(const RtspRangeType & range)935 OSCL_EXPORT_REF int estimate_SDP_string_len(const RtspRangeType& range)
936 {
937 // this function computes the string size necessary for
938 // holding the SDP string representation of the range
939
940 int total_len = 0;
941
942 total_len += 8 ; // this the length of the "a=range:" string
943
944 switch (range.format)
945 {
946
947 case RtspRangeType::NPT_RANGE:
948 total_len += 4; // this is the length of the "npt=" string
949
950 if (range.start_is_set)
951 {
952 total_len += estimate_SDP_string_len(range.npt_start);
953 }
954 else if (!range.end_is_set)
955 {
956 // return 0 in this case
957 return 0;
958 }
959
960 total_len += 1; // enough for "-"
961
962 if (range.end_is_set)
963 {
964 total_len += estimate_SDP_string_len(range.npt_end);
965 }
966
967 total_len += 2; // enough for CRLF at the end of the line
968
969 break;
970
971
972 case RtspRangeType::SMPTE_RANGE:
973 case RtspRangeType::SMPTE_25_RANGE:
974 case RtspRangeType::SMPTE_30_RANGE:
975 if (range.format == RtspRangeType::SMPTE_30_RANGE)
976 {
977 total_len += 14; // this is the length of the "smpte-30-drop=" string
978 }
979 else if (range.format == RtspRangeType::SMPTE_25_RANGE)
980 {
981 total_len += 9; // this is the length of the "smpte-25=" string
982 }
983 else
984 {
985 total_len += 6; // this is enough for "smpte="
986 }
987
988 if (range.start_is_set)
989 {
990 total_len += 8; // enough for "XX:YY:ZZ"
991 if (range.smpte_start.frames || range.smpte_start.subframes)
992 {
993 total_len += 3; // enough for ":FF"
994 if (range.smpte_start.subframes)
995 {
996 total_len += 3; // enough for ".SS"
997 }
998 }
999 }
1000 else if (!range.end_is_set)
1001 {
1002 // return 0 in this case
1003 return 0;
1004 }
1005
1006 total_len += 1; // enough for "-"
1007
1008 if (range.end_is_set)
1009 {
1010 total_len += 8; // enough for "XX:YY:ZZ"
1011 if (range.smpte_end.frames || range.smpte_end.subframes)
1012 {
1013 total_len += 3; // enough for ":FF"
1014 if (range.smpte_end.subframes)
1015 {
1016 total_len += 3; // enough for ".SS"
1017 }
1018 }
1019 }
1020
1021 total_len += 2; // enough for CRLF at the end of the line
1022
1023 break;
1024
1025 case RtspRangeType::ABS_RANGE:
1026
1027 total_len += 6; // this is the length of the "clock=" string
1028
1029 if (range.start_is_set)
1030 {
1031 total_len += 15; // enough for "YYYYMMDDTHHMMSS"
1032 if (range.abs_start.frac_sec > 0.0)
1033 {
1034 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits
1035 }
1036 total_len += 1; // enough for the "Z"
1037 }
1038 else if (!range.end_is_set)
1039 {
1040 // return 0 in this case
1041 return 0;
1042 }
1043
1044 total_len += 1; // enough for "-"
1045
1046 if (range.end_is_set)
1047 {
1048 total_len += 15; // enough for "YYYYMMDDTHHMMSS"
1049 if (range.abs_end.frac_sec > 0.0)
1050 {
1051 total_len += MAX_RANGE_FLOAT_SIZE; // includes "." and all digits
1052 }
1053 total_len += 1; // enough for the "Z"
1054 }
1055
1056 total_len += 2; // enough for CRLF at the end of the line
1057
1058 break;
1059
1060
1061 default:
1062 return 0;
1063 break;
1064 }
1065
1066 return total_len;
1067 }
1068
1069
1070
compose_range_string(char * str,unsigned int max_len,const NptTimeFormat & npt_range,int & len_used)1071 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len,
1072 const NptTimeFormat& npt_range,
1073 int& len_used)
1074 {
1075 len_used = 0;
1076 int length;
1077
1078
1079 switch (npt_range.npt_format)
1080 {
1081 case NptTimeFormat::NOW:
1082 {
1083 StrPtrLen now_str("now");
1084 if ((int)max_len < now_str.length())
1085 {
1086 return false;
1087 }
1088 oscl_memcpy(str, now_str.c_str(), now_str.length());
1089 str += now_str.length();
1090 len_used += now_str.length();
1091 max_len -= now_str.length();
1092 break;
1093 }
1094
1095 case NptTimeFormat::NPT_SEC:
1096 {
1097 char tmpstr[MAX_RANGE_INT_SIZE + 1];
1098 length = oscl_snprintf(tmpstr, MAX_RANGE_INT_SIZE + 1, "%d",
1099 npt_range.npt_sec.sec);
1100 if (length < 0 || length > MAX_RANGE_INT_SIZE)
1101 {
1102 return false;
1103 }
1104 if (length > (int) max_len)
1105 {
1106 return false;
1107 }
1108 oscl_memcpy(str, tmpstr, length);
1109 str += length;
1110 len_used += length;
1111 max_len -= length;
1112 if (npt_range.npt_sec.milli_sec > 0.0)
1113 {
1114 if (npt_range.npt_sec.milli_sec >= 1.0)
1115 {
1116 return false;
1117 }
1118 char tmp[MAX_RANGE_FLOAT_SIZE + 2];
1119 length = oscl_snprintf(tmp, MAX_RANGE_FLOAT_SIZE + 2, RANGE_FLOAT_FORMAT,
1120 npt_range.npt_sec.milli_sec);
1121 if (length < 0 || length > MAX_RANGE_FLOAT_SIZE + 1)
1122 {
1123 return false;
1124 }
1125 if (length > (int)max_len || tmp[1] != '.')
1126 {
1127 return false;
1128 }
1129
1130 oscl_memcpy(str, tmp + 1, length - 1);
1131 str += length - 1;
1132 len_used += length - 1;
1133 max_len -= (length - 1);
1134 }
1135
1136 break;
1137 }
1138
1139 case NptTimeFormat::NPT_HHMMSS:
1140 {
1141 char tmpstr[MAX_RANGE_INT_SIZE + 1];
1142 length = oscl_snprintf(tmpstr, MAX_RANGE_INT_SIZE + 1, "%d",
1143 npt_range.npt_hhmmss.hours);
1144 if (length < 0 || length >= MAX_RANGE_INT_SIZE)
1145 {
1146 return false;
1147 }
1148 if (length > (int) max_len)
1149 {
1150 return false;
1151 }
1152 oscl_memcpy(str, tmpstr, length);
1153 str += length;
1154 len_used += length;
1155 max_len -= length;
1156
1157 if (max_len < 6)
1158 {
1159 return false;
1160 }
1161
1162 length = oscl_snprintf(tmpstr, MAX_RANGE_INT_SIZE + 1, ":%02d:%02d",
1163 npt_range.npt_hhmmss.min, npt_range.npt_hhmmss.sec);
1164 if (length != 6)
1165 {
1166 return false;
1167 }
1168
1169 oscl_memcpy(str, tmpstr, length);
1170 str += length;
1171 len_used += length;
1172 max_len -= length;
1173
1174
1175 if (npt_range.npt_hhmmss.frac_sec > 0.0)
1176 {
1177 if (npt_range.npt_hhmmss.frac_sec >= 1.0)
1178 {
1179 return false;
1180 }
1181 char tmp[MAX_RANGE_FLOAT_SIZE + 2];
1182 length = oscl_snprintf(tmp, MAX_RANGE_FLOAT_SIZE + 2, RANGE_FLOAT_FORMAT,
1183 npt_range.npt_hhmmss.frac_sec);
1184 if (length < 0 || length > MAX_RANGE_FLOAT_SIZE + 1)
1185 {
1186 return false;
1187 }
1188 if (length > (int) max_len || tmp[1] != '.')
1189 {
1190 return false;
1191 }
1192
1193 oscl_memcpy(str, tmp + 1, length - 1);
1194 str += length - 1;
1195 len_used += length - 1;
1196 max_len -= (length - 1);
1197 }
1198
1199 break;
1200 }
1201
1202 }
1203
1204 return true;
1205
1206 }
1207
1208
compose_range_string(char * str,unsigned int max_len,const SmpteTimeFormat & smpte_range,int & len_used)1209 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len,
1210 const SmpteTimeFormat& smpte_range,
1211 int& len_used)
1212 {
1213 len_used = 0;
1214 int length;
1215
1216
1217 char tmp[10];
1218
1219 if (max_len < 8)
1220 {
1221 return false;
1222 }
1223
1224 length = oscl_snprintf(tmp, 9, "%02d:%02d:%02d", smpte_range.hours,
1225 smpte_range.minutes, smpte_range.seconds);
1226
1227 if (length != 8)
1228 {
1229 return false;
1230 }
1231
1232 oscl_memcpy(str, tmp , length);
1233 str += length;
1234 len_used += length;
1235 max_len -= length;
1236
1237 if (smpte_range.frames)
1238 {
1239 if (max_len < 3)
1240 {
1241 return 0;
1242 }
1243 length = oscl_snprintf(tmp, 4, ":%02d", smpte_range.frames);
1244 if (length != 3)
1245 {
1246 return false;
1247 }
1248
1249 oscl_memcpy(str, tmp , length);
1250 str += length;
1251 len_used += length;
1252 max_len -= length;
1253 }
1254
1255 if (smpte_range.subframes)
1256 {
1257 if (max_len < 3)
1258 {
1259 return 0;
1260 }
1261 length = oscl_snprintf(tmp, 4, ".%02d", smpte_range.subframes);
1262 if (length != 3)
1263 {
1264 return false;
1265 }
1266
1267 oscl_memcpy(str, tmp , length);
1268 str += length;
1269 len_used += length;
1270 max_len -= length;
1271 }
1272
1273 return true;
1274
1275 }
1276
1277
compose_range_string(char * str,unsigned int max_len,const AbsTimeFormat & abs_range,int & len_used)1278 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len,
1279 const AbsTimeFormat& abs_range,
1280 int& len_used)
1281 {
1282 len_used = 0;
1283 int length;
1284
1285
1286 char tmp[17];
1287
1288 if (max_len < 16)
1289 {
1290 return false;
1291 }
1292
1293 length = oscl_snprintf(tmp, 17, "%04d%02d%02dT%02d%02d%02d",
1294 abs_range.year, abs_range.month, abs_range.day,
1295 abs_range.hours, abs_range.min, abs_range.sec);
1296
1297 if (length != 15)
1298 {
1299 return false;
1300 }
1301
1302 oscl_memcpy(str, tmp , length);
1303 str += length;
1304 len_used += length;
1305 max_len -= length;
1306
1307 if (abs_range.frac_sec > 0.0)
1308 {
1309 if (abs_range.frac_sec >= 1.0)
1310 {
1311 return false;
1312 }
1313 char tmpstr[MAX_RANGE_FLOAT_SIZE + 2];
1314 length = oscl_snprintf(tmpstr, MAX_RANGE_FLOAT_SIZE + 2, RANGE_FLOAT_FORMAT,
1315 abs_range.frac_sec);
1316 if (length < 0 || length > MAX_RANGE_FLOAT_SIZE + 1)
1317 {
1318 return false;
1319 }
1320 if (length > (int)max_len || tmp[1] != '.')
1321 {
1322 return false;
1323 }
1324
1325 oscl_memcpy(str, tmp + 1, length - 1);
1326 str += length - 1;
1327 len_used += length - 1;
1328 max_len -= (length - 1);
1329 }
1330
1331 if (max_len < 1)
1332 {
1333 return false;
1334 }
1335
1336 *str = 'Z';
1337 len_used++;
1338
1339 return true;
1340
1341 }
1342
1343
compose_range_string(char * str,unsigned int max_len,const RtspRangeType & range,int & len_used)1344 OSCL_EXPORT_REF bool compose_range_string(char *str, unsigned int max_len, const RtspRangeType& range,
1345 int& len_used)
1346 {
1347 len_used = 0;
1348 int length;
1349
1350 if (!range.start_is_set && !range.end_is_set)
1351 {
1352 return false;
1353 }
1354
1355 switch (range.format)
1356 {
1357 case RtspRangeType::NPT_RANGE:
1358 {
1359 StrPtrLen npt_str("npt=");
1360
1361 if (max_len < (unsigned int)npt_str.length())
1362 {
1363 return false;
1364 }
1365
1366 oscl_memcpy(str, npt_str.c_str(), npt_str.length());
1367
1368 str += npt_str.length();
1369 max_len -= npt_str.length();
1370 len_used += npt_str.length();
1371
1372 if (range.start_is_set)
1373 {
1374 if (compose_range_string(str, max_len, range.npt_start,
1375 length) != true)
1376 {
1377 return false;
1378 }
1379
1380 len_used += length;
1381 max_len -= length;
1382 str += length;
1383 }
1384
1385 if (max_len < 1)
1386 {
1387 return false;
1388 }
1389
1390 *str++ = '-';
1391 --max_len;
1392 ++len_used;
1393
1394 if (range.end_is_set)
1395 {
1396 if (compose_range_string(str, max_len, range.npt_end,
1397 length) != true)
1398 {
1399 return false;
1400 }
1401
1402 len_used += length;
1403 max_len -= length;
1404 str += length;
1405 }
1406
1407 break;
1408 }
1409
1410 case RtspRangeType::SMPTE_RANGE:
1411 case RtspRangeType::SMPTE_25_RANGE:
1412 case RtspRangeType::SMPTE_30_RANGE:
1413 {
1414 StrPtrLen smpte30_str("smpte-30-drop=");
1415 StrPtrLen smpte25_str("smpte-25=");
1416 StrPtrLen smpte_str("smpte=");
1417
1418 if (range.format == RtspRangeType::SMPTE_30_RANGE)
1419 {
1420 if (max_len < (unsigned int)smpte30_str.length())
1421 {
1422 return false;
1423 }
1424 oscl_memcpy(str, smpte30_str.c_str(), smpte30_str.length());
1425
1426 str += smpte30_str.length();
1427 max_len -= smpte30_str.length();
1428 len_used += smpte30_str.length();
1429
1430 }
1431 else if (range.format == RtspRangeType::SMPTE_25_RANGE)
1432 {
1433 if (max_len < (unsigned int)smpte25_str.length())
1434 {
1435 return false;
1436 }
1437
1438 oscl_memcpy(str, smpte25_str.c_str(), smpte25_str.length());
1439
1440 str += smpte25_str.length();
1441 max_len -= smpte25_str.length();
1442 len_used += smpte25_str.length();
1443 }
1444 else
1445 {
1446 if (max_len < (unsigned int)smpte_str.length())
1447 {
1448 return false;
1449 }
1450
1451 oscl_memcpy(str, smpte_str.c_str(), smpte_str.length());
1452 str += smpte_str.length();
1453 max_len -= smpte_str.length();
1454 len_used += smpte_str.length();
1455
1456 }
1457
1458 if (range.start_is_set)
1459 {
1460 if (compose_range_string(str, max_len, range.smpte_start,
1461 length) != true)
1462 {
1463 return false;
1464 }
1465
1466 len_used += length;
1467 max_len -= length;
1468 str += length;
1469 }
1470
1471 if (max_len < 1)
1472 {
1473 return false;
1474 }
1475
1476 *str++ = '-';
1477 --max_len;
1478 ++len_used;
1479
1480
1481 if (range.end_is_set)
1482 {
1483 if (compose_range_string(str, max_len, range.smpte_end,
1484 length) != true)
1485 {
1486 return false;
1487 }
1488
1489 len_used += length;
1490 max_len -= length;
1491 str += length;
1492 }
1493
1494 break;
1495 }
1496
1497 case RtspRangeType::ABS_RANGE:
1498 {
1499 StrPtrLen abs_str("clock=");
1500
1501 if (max_len < (unsigned int)abs_str.length())
1502 {
1503 return false;
1504 }
1505
1506 oscl_memcpy(str, abs_str.c_str(), abs_str.length());
1507
1508 str += abs_str.length();
1509 max_len -= abs_str.length();
1510 len_used += abs_str.length();
1511
1512 if (range.start_is_set)
1513 {
1514 if (compose_range_string(str, max_len, range.abs_start,
1515 length) != true)
1516 {
1517 return false;
1518 }
1519
1520 len_used += length;
1521 max_len -= length;
1522 str += length;
1523 }
1524
1525 if (max_len < 1)
1526 {
1527 return false;
1528 }
1529
1530 *str++ = '-';
1531 --max_len;
1532 ++len_used;
1533
1534
1535 if (range.end_is_set)
1536 {
1537 if (compose_range_string(str, max_len, range.abs_end,
1538 length) != true)
1539 {
1540 return false;
1541 }
1542
1543 len_used += length;
1544 max_len -= length;
1545 str += length;
1546 }
1547
1548 break;
1549 }
1550
1551 default:
1552 return false;
1553 }
1554
1555 if (max_len < 2)
1556 {
1557 // can't add line terminator
1558 return false;
1559 }
1560
1561 // add the line terminator
1562 *str++ = '\r';
1563 *str++ = '\n';
1564 len_used += 2;
1565
1566
1567 return true;
1568
1569 }
1570
1571
1572
1573
compose_SDP_string(char * str,unsigned int max_len,const RtspRangeType & range,int & len_used)1574 OSCL_EXPORT_REF bool compose_SDP_string(char *str, unsigned int max_len,
1575 const RtspRangeType& range,
1576 int& len_used)
1577 {
1578 len_used = 0;
1579
1580 // first verify that there is something to do
1581 if (range.format == RtspRangeType::UNKNOWN_RANGE ||
1582 range.format == RtspRangeType::INVALID_RANGE)
1583 {
1584 // nothing to output but it is not an error
1585 return true;
1586 }
1587
1588 const char *range_str = "a=range:";
1589 int length = oscl_strlen(range_str);
1590 // output the "a=range:" string
1591 if ((int)max_len < length)
1592 {
1593 return false;
1594 }
1595
1596 oscl_memcpy(str, range_str, length);
1597
1598 str += length;
1599 len_used += length;
1600 max_len -= length;
1601
1602 if (compose_range_string(str, max_len, range, length) != true)
1603 {
1604 len_used += length;
1605 return false;
1606 }
1607
1608 len_used += length;
1609
1610 return true;
1611 }
1612
1613
1614
compose_RTSP_string(char * str,unsigned int max_len,const RtspRangeType & range,int & len_used)1615 OSCL_EXPORT_REF bool compose_RTSP_string(char *str, unsigned int max_len,
1616 const RtspRangeType& range,
1617 int& len_used)
1618 {
1619 len_used = 0;
1620
1621 // first verify that there is something to do
1622 if (range.format == RtspRangeType::UNKNOWN_RANGE ||
1623 range.format == RtspRangeType::INVALID_RANGE)
1624 {
1625 // nothing to output but it is not an error
1626 return true;
1627 }
1628
1629 const char *range_str = "Range: ";
1630 int length = oscl_strlen(range_str);
1631 // output the "Range: " string
1632 if ((int)max_len < length)
1633 {
1634 return false;
1635 }
1636
1637 oscl_memcpy(str, range_str, length);
1638
1639 str += length;
1640 len_used += length;
1641 max_len -= length;
1642
1643 if (compose_range_string(str, max_len, range, length) != true)
1644 {
1645 len_used += length;
1646 return false;
1647 }
1648
1649 len_used += length;
1650
1651 return true;
1652 }
1653
1654
1655
1656
1657