• 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 #include "sdp_parser.h"
19 #include "sdp_mediaparser_registry.h"
20 #include "oscl_string_utils.h"
21 #include "oscl_string_containers.h"
22 #include "oscl_str_ptr_len.h"
23 #include "base_media_info_parser.h"
24 #include "aac_media_info_parser.h"
25 #include "amr_media_info_parser.h"
26 #include "h263_media_info_parser.h"
27 #include "m4v_media_info_parser.h"
28 #include "still_image_media_info_parser.h"
29 #include "pcma_media_info_parser.h"
30 #include "pcmu_media_info_parser.h"
31 #include "oscl_vector.h"
32 #include "oscl_dll.h"
33 
34 OSCL_DLL_ENTRY_POINT_DEFAULT()
35 struct mime_payload_pair
36 {
37     OsclMemoryFragment mime;
38     Oscl_Vector<int, SDPParserAlloc> payload_no;
39 };
40 
SDP_Parser(SDPMediaParserRegistry * & regTable,bool sipSdp)41 OSCL_EXPORT_REF SDP_Parser::SDP_Parser(SDPMediaParserRegistry*& regTable, bool sipSdp):
42         iLogger(NULL),
43         _pSDPMediaParserRegistry(regTable),
44         mediaArrayIndex(0),
45         applicationFlag(false),
46         isSipSdp(sipSdp)
47 {
48     iLogger = PVLogger::GetLoggerObject("SDP_Parser");
49 }
50 
51 
~SDP_Parser()52 OSCL_EXPORT_REF SDP_Parser::~SDP_Parser()
53 {
54 }
55 
parse_rtpmap(const char * start,const char * end,int & rtp_payload,OsclMemoryFragment & encoding_name)56 bool SDP_Parser::parse_rtpmap(const char *start, const char *end, int& rtp_payload,
57                               OsclMemoryFragment& encoding_name)
58 {
59     const int len_of_rtpmap = 9;
60 
61     // grab the endpoints
62     const char *sptr = start + len_of_rtpmap;
63     const char *eptr;
64 
65     // skip to the first whitespace character
66     eptr = skip_to_whitespace(sptr, end);
67     if (eptr < sptr)
68     {
69         return false;
70     }
71     uint32 rtpPayload;
72     if (PV_atoi(sptr, 'd', (eptr - sptr), rtpPayload) == false)
73     {
74         return false;
75     }
76     rtp_payload = (int)rtpPayload;
77 
78     // now get the encoding name
79     sptr = skip_whitespace(eptr, end);
80     if (sptr >= end)
81     {
82         return false;
83     }
84 
85     // now skip to end of the encoding name
86     for (eptr = sptr; eptr < end &&
87             (*eptr != ' ' && *eptr != '\t' && *eptr != '/');
88             ++eptr);
89 
90     if (eptr >= end)
91     {
92         return false;
93     }
94 
95     encoding_name.ptr = (void *) sptr;
96     encoding_name.len = eptr - sptr;
97 
98     return true;
99 }
100 
101 
validate_media_line(const char * start,const char * end,Oscl_Vector<int,SDPParserAlloc> & payload_type,uint32 & portNumber)102 int SDP_Parser::validate_media_line(const char *start, const char *end, Oscl_Vector<int, SDPParserAlloc>& payload_type, uint32& portNumber)
103 {
104     int len;
105     const char *sptr, *eptr;
106 
107     sptr = start + 2;  // start after the "m="
108     // skip to end of media type
109     eptr = skip_to_whitespace(sptr, end);
110     if (eptr >= end)
111     {
112         return 0;
113     }
114 
115 
116     len = eptr - sptr;
117     // make sure type is supported
118     if (!oscl_CIstrncmp(sptr, "audio", len) || !oscl_CIstrncmp(sptr, "video", len) ||
119             !oscl_CIstrncmp(sptr, "application", len))
120     {
121         // the type is supported
122         // make sure there is only one payload type in the format list
123 
124         // skip to start of port number
125         sptr = skip_whitespace(eptr, end);
126         if (sptr >= end)
127         {
128             return 0;
129         }
130 
131         // skip to end of port number
132         eptr = skip_to_whitespace(sptr, end);
133         if (eptr <= sptr)
134         {
135             return 0;
136         }
137 
138         const char *tmp_end_ptr = sptr;
139         const char SDP_FWD_SLASH[] = "/";
140 
141         OSCL_HeapString<SDPParserAlloc> restOfLine(tmp_end_ptr, eptr - tmp_end_ptr);
142         const char *slash = oscl_strstr(restOfLine.get_cstr(), SDP_FWD_SLASH);
143 
144         if (slash == NULL)
145         {
146             // Get the port number
147             if (PV_atoi(sptr, 'd', (eptr - sptr), portNumber) == false)
148             {
149                 return 0;
150             }
151         }
152         else
153         {
154             // Get the port number
155             if (PV_atoi(restOfLine.get_cstr(), 'd', (slash - restOfLine.get_cstr()), portNumber) == false)
156             {
157                 return 0;
158             }
159         }
160 
161         // skip to start of transport
162         sptr = skip_whitespace(eptr, end);
163         if (sptr >= end)
164         {
165             return 0;
166         }
167 
168         // skip to end of transport
169         eptr = skip_to_whitespace(sptr, end);
170         if (eptr <= sptr)
171         {
172             return 0;
173         }
174 
175         // skip to start of format list
176         sptr = skip_whitespace(eptr, end);
177         if (sptr >= end)
178         {
179             return 0;
180         }
181 
182         // skip to end of first payload arg
183         eptr = skip_to_whitespace(sptr, end);
184         if (eptr <= sptr)
185         {
186             return 0;
187         }
188 
189         // record the payload type for non-application m= lines
190         if (oscl_strncmp(start + 2, "application", len))
191         {
192             uint32 payloadType;
193 
194             while (sptr < end)
195             {
196                 if (PV_atoi(sptr, 'd', (eptr - sptr), payloadType) == false)
197                 {
198                     return 0;
199                 }
200 
201                 payload_type.push_back(payloadType);
202 
203                 sptr = skip_to_whitespace(sptr, end);
204                 sptr = skip_whitespace_and_line_term(eptr, end);
205                 eptr = skip_whitespace_and_line_term(eptr, end);
206                 eptr = skip_to_whitespace(eptr, end);
207             }
208         }
209         else
210         {
211             uint32 len = OSCL_MIN((uint32)(eptr - start), oscl_strlen("IMAGE"));
212             if (!oscl_strncmp(start, "IMAGE", len))
213             {
214                 applicationFlag = true;
215             }
216             else    //don't support this media. so skip the section
217                 return 0;
218         }
219 
220         if (sptr < end)
221         {
222             return 0;
223         }
224 
225         return 1;
226     }
227 
228     return 0;
229 
230 }
231 
232 OSCL_EXPORT_REF
parseSDP(const char * sdpText,int text_length,SDPInfo * sdp)233 SDP_ERROR_CODE SDP_Parser::parseSDP(const char *sdpText, int text_length, SDPInfo *sdp)
234 {
235     int index = 0, sdpIndex = 0;
236 
237     const char *end_ptr = sdpText + text_length ; // Point just beyond the end
238     const char *section_start_ptr;
239     const char *section_end_ptr;
240     const char *line_start_ptr, *line_end_ptr;
241     bool session_info_parsed = false;
242 
243     /**************************************************************************/
244 
245     // The purpose of this outer loop is to partition the SDP into different
246     // sections to be passed off to session-level parsers or media-level parsers.
247     // We just need to find the boundaries and pass the appropriate sections
248     // of code to the subparsers.
249 
250     sdpIndex = 0;
251     index = 0;
252 
253     // these track whether media and session-level sections have already
254     // been found
255     int media_sections_found = 0;
256     int session_section_found = 0;
257 
258     // skip any leading whitespace including line terminators
259     section_start_ptr = skip_whitespace_and_line_term(sdpText, end_ptr);
260 
261     while ((section_start_ptr - sdpText) < text_length)
262     {
263         if (!get_next_line(section_start_ptr, end_ptr,
264                            line_start_ptr, line_end_ptr))
265         {
266             break;
267         }
268 
269         // figure out the type of section
270         if (!oscl_strncmp(line_start_ptr, "v=", 2))
271         {
272             // this is the session-level
273             if (media_sections_found || session_section_found)
274             {
275                 // there were already media sections or already a session-level section
276                 // so a session-level section at this point is not allowed.
277                 PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Duplicate Session Sections"));
278                 return SDP_BAD_FORMAT;
279             }
280 
281             section_end_ptr = line_end_ptr;
282 
283             // record that the session-level section has been found
284             session_section_found = 1;
285 
286             while (get_next_line(section_end_ptr, end_ptr,
287                                  line_start_ptr, line_end_ptr))
288             {
289                 // check if this is the start of another section
290                 if (!oscl_strncmp(line_start_ptr, "v=", 2) ||
291                         !oscl_strncmp(line_start_ptr, "m=", 2))
292                 {
293                     break;
294                 }
295                 section_end_ptr = line_end_ptr;
296             }
297 
298 
299             OsclMemoryFragment session_frag;
300             session_frag.ptr = (void *)section_start_ptr;
301             session_frag.len = section_end_ptr - section_start_ptr;
302 
303             SDP_ERROR_CODE retval =
304                 parseSDPSessionInfo(section_start_ptr,
305                                     section_end_ptr - section_start_ptr,
306                                     sdp);
307             if (retval != SDP_SUCCESS)
308             {
309                 PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - parseSDPSessionInfo Failed=%d", retval));
310                 return retval;
311             }
312             else
313             {
314                 session_info_parsed = true;
315             }
316         }
317         else if (!oscl_strncmp(line_start_ptr, "m=", 2))
318         {
319 
320             // now look for the end of the section
321             section_end_ptr = line_end_ptr;
322             bool supported_media = true;
323 
324             ++media_sections_found;
325             sdp->setSegmentCount(media_sections_found);
326 
327             /* SUPPORTING MULTIPLE PAYLOAD TYPE PER MEDIA NOW */
328             // check to see how many payload types are present
329             Oscl_Vector<int, SDPParserAlloc> payload_type;
330             Oscl_Vector<int, SDPParserAlloc> rtpmap_pt;
331             Oscl_Vector<OsclMemoryFragment, SDPParserAlloc> encoding_name_vector;
332 
333             uint32 portNumber = 0;
334             if (!validate_media_line(line_start_ptr, line_end_ptr, payload_type, portNumber))
335             {
336                 // skip this section
337                 supported_media = false;
338             }
339             else
340             {
341                 PVMF_SDP_PARSER_LOGINFO((0, "SDP_Parser::parseSDP - Validated MediaSection"));
342             }
343 
344             int rtpmap_lines = 0;
345 
346             // get the next line
347             OsclMemoryFragment encoding_name;
348             encoding_name.ptr = NULL;
349             encoding_name.len = 0;
350 
351             Oscl_Vector<int, SDPParserAlloc> AltId;
352             while (get_next_line(section_end_ptr, end_ptr, line_start_ptr, line_end_ptr))
353             {
354                 // check if this is the start of another section
355                 if (!oscl_strncmp(line_start_ptr, "v=", 2) ||
356                         !oscl_strncmp(line_start_ptr, "m=", 2))
357                 {
358                     break;
359                 }
360                 if (supported_media && (applicationFlag == false))
361                 {
362                     // check for lines which will give the media type
363                     // so the parser can be allocated. Simply look for
364                     // the "a=rtpmap" lines which contain the MIME type.
365                     StrPtrLen rtpmap_str("a=rtpmap:");
366                     if (!oscl_strncmp(line_start_ptr, rtpmap_str.c_str(), rtpmap_str.length()))
367                     {
368                         ++rtpmap_lines;
369                         int rtpmap_cu;
370                         // get encoding name
371                         if (!parse_rtpmap(line_start_ptr, line_end_ptr, rtpmap_cu, encoding_name))
372                         {
373                             // invalid format
374                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - parse_rtpmap Failed"));
375                             return SDP_BAD_MEDIA_FORMAT;
376                         }
377                         rtpmap_pt.push_back(rtpmap_cu);
378                         encoding_name_vector.push_back(encoding_name);
379                         OSCL_StackString<15> mime((const char*)(encoding_name.ptr), encoding_name.len);
380                         PVMF_SDP_PARSER_LOGINFO((0, "SDP_Parser::parseSDP - a=rtpmap mime=%s", mime.get_cstr()));
381                     }
382                     StrPtrLen alt_def("a=alt-default-id:");
383                     if (!oscl_strncmp(line_start_ptr, alt_def.c_str(), alt_def.length()))
384                     {
385                         uint32 id;
386                         const char *sptr = line_start_ptr + alt_def.length();
387                         sptr = skip_whitespace(sptr, line_end_ptr);
388                         if (!PV_atoi(sptr, 'd', line_end_ptr - sptr, id))
389                         {
390                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing a=alt-default-id: Failed"));
391                             return SDP_BAD_MEDIA_ALT_ID;
392                         }
393                         AltId.push_back(id);
394                     }
395                     StrPtrLen alt_id("a=alt:");
396                     if (!oscl_strncmp(line_start_ptr, alt_id.c_str(), alt_id.length()))
397                     {
398                         uint32 id;
399                         const char *sptr = line_start_ptr + alt_id.length();
400                         sptr = skip_whitespace(sptr, line_end_ptr);
401                         const char *eptr = sptr;
402                         for (; *eptr != ':'; eptr++);
403                         if (!PV_atoi(sptr, 'd', eptr - sptr, id))
404                         {
405                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing a=alt: Failed"));
406                             return SDP_BAD_MEDIA_ALT_ID;
407                         }
408                         if (AltId.back() != (int)id)
409                             AltId.push_back(id);
410                     }
411 
412                     // fmtp and framesize payload check is provided below
413                     // this is done to make sure that the payload coming in these fields
414                     // is one of the payloads in the m= segment
415                     StrPtrLen fmtp("a=fmtp:");
416                     if (!oscl_strncmp(line_start_ptr, fmtp.c_str(), fmtp.length()))
417                     {
418                         uint32 payload;
419                         const char *sptr = line_start_ptr + fmtp.length();
420                         sptr = skip_whitespace(sptr, line_end_ptr);
421                         const char* eptr = skip_to_whitespace(sptr, line_end_ptr);
422                         if (!PV_atoi(sptr, 'd', eptr - sptr, payload))
423                         {
424                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing a=fmtp: Failed"));
425                             return SDP_BAD_MEDIA_FORMAT;
426                         }
427                         // The format is proper match the payload with payloads in m= segment
428                         bool matched = false;
429                         for (uint32 ii = 0; ii < payload_type.size(); ii++)
430                         {
431                             if (payload == (uint32)payload_type[ii])
432                             {
433                                 matched = true;
434                                 break;
435                             }
436                         }
437                         if (!matched)
438                         {
439                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Payload Mismatch in fmtp line"));
440                             return SDP_PAYLOAD_MISMATCH;
441                         }
442                     }
443                     StrPtrLen framesize("a=framesize:");
444                     if (!oscl_strncmp(line_start_ptr, framesize.c_str(), framesize.length()))
445                     {
446                         uint32 payload;
447                         const char *sptr = line_start_ptr + framesize.length();
448                         sptr = skip_whitespace(sptr, line_end_ptr);
449                         const char* eptr = skip_to_whitespace(sptr, line_end_ptr);
450                         if (!PV_atoi(sptr, 'd', eptr - sptr, payload))
451                         {
452                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing a=framesize: Failed"));
453                             return SDP_BAD_MEDIA_FORMAT;
454                         }
455                         // The format is proper match the payload with payloads in m= segment
456                         bool matched = false;
457                         for (uint32 ii = 0; ii < payload_type.size(); ii++)
458                         {
459                             if (payload == (uint32)payload_type[ii])
460                             {
461                                 matched = true;
462                                 break;
463                             }
464                         }
465                         if (!matched)
466                         {
467                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Payload Mismatch in a=framesize: line"));
468                             return SDP_PAYLOAD_MISMATCH;
469                         }
470                     }
471 
472                 } // end if media is supported
473                 else
474                 {
475                     PVMF_SDP_PARSER_LOGINFO((0, "SDP_Parser::parseSDP - Skipping over an entire m= section"));
476                 }
477 
478                 section_end_ptr = line_end_ptr;
479             } // end loop over the entire media section
480 
481 
482             // The checking for rtpmap vs payloads is not required if the port number is 0 in case it is a sip sdp
483             bool check_for_rtpmap = true;
484             if (isSipSdp && portNumber == 0)
485             {
486                 check_for_rtpmap = false;
487             }
488 
489             // Checking for rtpmap with the payloads
490             if (supported_media && check_for_rtpmap)
491             {
492                 // Validate the payload type and rtpmap if required
493                 int static_payload_count = 0;
494                 int ii = 0;
495                 for (; ii < (int)payload_type.size(); ii++)
496                 {
497                     // If any payload_type is in static range we do not care
498                     // for the rtpmap field. We will process for this static payload type sdp
499                     // the dynamic payload type if any will be ignored if it's rtpmap
500                     // is missing
501                     if ((payload_type[ii] >= FIRST_STATIC_PAYLOAD) &&
502                             (payload_type[ii] <= LAST_STATIC_PAYLOAD))
503                     {
504                         PVMF_SDP_PARSER_LOGINFO((0, "SDP_Parser::parseSDP - Static Payload =%d", payload_type[ii]));
505                         static_payload_count++;
506                     }
507                 }
508                 if (static_payload_count == 0)
509                 {
510                     // The payload type present are all in the dynamic range
511                     if (rtpmap_pt.size() != payload_type.size())
512                     {
513                         PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Mismatch between number of payloads and rtpmap lines"));
514                         return SDP_BAD_MEDIA_FORMAT;
515                     }
516                     for (int ii = 0; ii < (int)rtpmap_pt.size(); ii++)
517                     {
518                         if (rtpmap_pt[ii] != payload_type[ii])
519                         {
520                             // this is an error
521                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Incorrect payload number  in rtpmap line"));
522                             return SDP_PAYLOAD_MISMATCH;
523                         }
524                     }
525                 }
526                 else if (static_payload_count >= 1)
527                 {
528                     // All of the payloads can either be static or one of them
529                     // for every dynamic payload there should be matching rtpmap field
530                     if (rtpmap_pt.size() != (payload_type.size() - static_payload_count))
531                     {
532                         PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Mismatch between number of payloads and rtpmap lines"));
533                         return SDP_BAD_MEDIA_FORMAT;
534                     }
535                     for (uint32 rtpmap_count = 0; rtpmap_count < rtpmap_pt.size(); rtpmap_count++)
536                     {
537                         bool match_found = false;
538                         for (int jj = 0; jj < (int)payload_type.size(); jj++)
539                         {
540                             if (rtpmap_pt[rtpmap_count] == payload_type[jj])
541                             {
542                                 match_found = true;
543                                 break;
544                             }
545                         }
546                         if (match_found == false)
547                         {
548                             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - No matching rtpmap line"));
549                             // this is an error
550                             return SDP_PAYLOAD_MISMATCH;
551                         }
552                     }
553                 }
554             }
555 
556             if (session_info_parsed == false)
557             {
558                 PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Missing Session Section"));
559                 return SDP_BAD_FORMAT;
560             }
561 
562             if (supported_media)
563             {
564                 StrPtrLen image("X-MP4V-IMAGE");
565                 if (applicationFlag == true)
566                 {
567                     if (rtpmap_lines == 0)
568                     {
569                         rtpmap_lines++;
570                         encoding_name.ptr = (void *) image.c_str();
571                         encoding_name.len = image.length();
572                         applicationFlag = false;
573                         encoding_name_vector.push_back(encoding_name);
574                     }
575                 }
576 
577                 // Compose all media encoding names and put them in one vector
578                 // this will carry all encoding names including static and dynamic PT
579                 StrPtrLen pcma(PVMF_MIME_PCMA);
580                 StrPtrLen pcmu(PVMF_MIME_PCMU);
581                 StrPtrLen amr("AMR");
582                 Oscl_Vector<OsclMemoryFragment, SDPParserAlloc> all_media_encoding_names;
583                 uint32 ii = 0;
584                 uint32 jj = 0;
585                 for (; ii < payload_type.size(); ii++)
586                 {
587                     if (payload_type[ii] == PVMF_PCMU)
588                     {
589                         rtpmap_lines++;
590                         encoding_name.ptr = (void *) pcmu.c_str();
591                         encoding_name.len = pcmu.length();
592                     }
593                     else if (payload_type[ii] == PVMF_PCMA)
594                     {
595                         rtpmap_lines++;
596                         encoding_name.ptr = (void *) pcma.c_str();
597                         encoding_name.len = pcma.length();
598                     }
599                     else if (check_for_rtpmap == false)
600                     {
601                         // This means that the port is 0 and they payload is in dynamic range
602                         // rtpmap field is not present.
603                         // To map it internally let's put it under PCMU again
604                         rtpmap_lines++;
605                         encoding_name.ptr = (void *) pcmu.c_str();
606                         encoding_name.len = pcmu.length();
607                     }
608                     else
609                     {
610                         // All other payload encoding names are already present in the
611                         // encoding_name_vector.
612                         if (jj < encoding_name_vector.size())
613                         {
614                             encoding_name = encoding_name_vector[jj];
615                             jj++;
616                         }
617                     }
618                     all_media_encoding_names.push_back(encoding_name);
619                 }
620 
621                 // compose all the above information in the following format
622                 // Any Mime type coming repeatedly with different payload numbers
623                 // Then club them together
624                 Oscl_Vector<mime_payload_pair, SDPParserAlloc> mime_payload_pair_vector;
625 
626                 for (uint32 ll = 0; ll < payload_type.size(); ll++)
627                 {
628                     if (check_for_rtpmap == true)
629                     {
630                         bool matched = false;
631                         uint32 ii = 0;
632                         for (; ii < mime_payload_pair_vector.size(); ii++)
633                         {
634                             if (oscl_strncmp((char*)mime_payload_pair_vector[ii].mime.ptr,
635                                              (char*)all_media_encoding_names[ll].ptr,
636                                              all_media_encoding_names[ll].len) == 0)
637                             {
638                                 matched = true;
639                                 break;
640                             }
641                         }
642                         if (matched)
643                         {
644                             mime_payload_pair_vector[ii].payload_no.push_back(payload_type[ll]);
645                         }
646                         else
647                         {
648                             mime_payload_pair mpp;
649                             mpp.payload_no.push_back(payload_type[ll]);
650                             mpp.mime.len = all_media_encoding_names[ll].len;
651                             mpp.mime.ptr = all_media_encoding_names[ll].ptr;
652                             mime_payload_pair_vector.push_back(mpp);
653                         }
654                     }
655                     else
656                     {
657                         // It is a sip sdp with port = 0. Hence do not make specific checks
658                         mime_payload_pair mpp;
659                         mpp.payload_no.push_back(payload_type[ll]);
660                         mpp.mime.len = all_media_encoding_names[ll].len;
661                         mpp.mime.ptr = all_media_encoding_names[ll].ptr;
662                         mime_payload_pair_vector.push_back(mpp);
663                     }
664 
665                 }
666 
667                 if (rtpmap_lines >= 1)
668                 {
669                     SDPMediaParserFactory  *mediaParserFactory;
670                     SDPBaseMediaInfoParser *mediaParser;
671                     SDP_ERROR_CODE retval;
672 
673                     for (uint32 kk = 0; kk < mime_payload_pair_vector.size(); kk++)
674                     {
675                         encoding_name = mime_payload_pair_vector[kk].mime;
676                         if ((mediaParserFactory =
677                                     _pSDPMediaParserRegistry->lookupSDPMediaParserFactory(encoding_name)) != NULL)
678                         {
679                             mediaParser = mediaParserFactory->createSDPMediaParserInstance();
680                             if (mediaParser == NULL)
681                             {
682                                 PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Unable to create media parser"));
683                                 return SDP_FAILURE;
684                             }
685                             if (AltId.size() > 0)
686                             {
687                                 int alt_id;
688                                 bool alt_def_id = false;
689                                 for (int ss = 0; ss < (int)AltId.size(); ss++)
690                                 {
691                                     if (ss == 0) alt_def_id = true;
692                                     else alt_def_id = false;
693 
694                                     alt_id = AltId[ss];
695 
696                                     if ((retval = mediaParser->parseMediaInfo(section_start_ptr, section_end_ptr - section_start_ptr, sdp, mime_payload_pair_vector[kk].payload_no, isSipSdp, alt_id, alt_def_id)) != SDP_SUCCESS)
697                                     {
698                                         OSCL_StackString<8> mime((const char*)(encoding_name.ptr), encoding_name.len);
699                                         PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing m= section failed, mime=%s", mime.get_cstr()));
700                                         OSCL_DELETE((mediaParser));
701                                         sdp->freeLastMediaInfoObject();
702                                         return retval;
703                                     }
704 
705                                 }
706                             }
707                             else
708                             {
709                                 if ((retval = mediaParser->parseMediaInfo(section_start_ptr, section_end_ptr - section_start_ptr, sdp, mime_payload_pair_vector[kk].payload_no, isSipSdp)) != SDP_SUCCESS)
710                                 {
711                                     OSCL_StackString<8> mime((const char*)(encoding_name.ptr), encoding_name.len);
712                                     PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing m= section failed, mime=%s", mime.get_cstr()));
713                                     OSCL_DELETE((mediaParser));
714                                     sdp->freeLastMediaInfoObject();
715                                     return retval;
716                                 }
717                             }
718                             sdp->IncrementAlternateMediaInfoVectorIndex();
719                             OSCL_DELETE((mediaParser));
720                         }
721                         mediaParser = NULL;
722                     }   // End of for
723                 }
724                 if (rtpmap_lines == 0) // no rtpmap found in media
725                 {
726                     PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Parsing m= section failed, No rtpmap line"));
727                     return SDP_BAD_MEDIA_MISSING_RTPMAP;
728                 }
729             }
730         } // end this is a media section
731         else
732         {
733             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Unrecognized Syntax"));
734             // unknown section type -- this is an error
735             return SDP_FAILURE;
736         }
737 
738         section_start_ptr = skip_whitespace_and_line_term(section_end_ptr, end_ptr);
739 
740     }
741     {
742         //for SDP which doesn't have session level range, set the session level range
743         //to be the MAX of media ranges.
744         if (NULL == sdp->getSessionInfo())
745         {
746             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Missing Session Info"));
747             return SDP_BAD_FORMAT;
748         }
749         RtspRangeType *mySdpRange = ((RtspRangeType *)sdp->getSessionInfo()->getRange());
750         if (NULL == mySdpRange)
751         {
752             PVMF_SDP_PARSER_LOGERROR((0, "SDP_Parser::parseSDP - Unable to retrieve session range"));
753             return SDP_BAD_FORMAT;
754         }
755         if (mySdpRange->format == RtspRangeType::INVALID_RANGE)
756         {
757             PVMF_SDP_PARSER_LOGINFO((0, "SDP_Parser::parseSDP - No Valid Session Range - Setting it to Max of all media ranges"));
758             for (int32 i = sdp->getNumMediaObjects() - 1; i >= 0; i--)
759             {
760                 Oscl_Vector<mediaInfo*, SDPParserAlloc> mediaInfoVec =
761                     sdp->getMediaInfo(i);
762                 for (uint32 j = 0; j < mediaInfoVec.size(); j++)
763                 {
764                     mediaInfo* mInfo = mediaInfoVec[j];
765                     if (mInfo == NULL)
766                     {
767                         continue;
768                     }
769                     const RtspRangeType *mInfoSdpRange = mInfo->getRtspRange();
770                     if (NULL == mInfoSdpRange)
771                     {
772                         continue;
773                     }
774                     if (mInfoSdpRange->format != RtspRangeType::NPT_RANGE)
775                     {
776                         continue;
777                     }
778                     if (mySdpRange->format == RtspRangeType::INVALID_RANGE)
779                     {
780                         *mySdpRange = *mInfoSdpRange;
781                     }
782                     if (!mInfoSdpRange->end_is_set)
783                     {//live streaming
784                         *mySdpRange = *mInfoSdpRange;
785                         mySdpRange->start_is_set = true;//just to make sure
786                         mySdpRange->npt_start.npt_format = NptTimeFormat::NOW;
787                         return SDP_SUCCESS;
788                     }
789                     if (mInfoSdpRange->npt_start.npt_format == NptTimeFormat::NPT_SEC)
790                     {
791                         if (mInfoSdpRange->npt_start.npt_sec.sec < mySdpRange->npt_start.npt_sec.sec)
792                         {
793                             mySdpRange->npt_start.npt_sec = mInfoSdpRange->npt_start.npt_sec;
794                         }
795                         else if ((mInfoSdpRange->npt_start.npt_sec.sec == mySdpRange->npt_start.npt_sec.sec)
796                                  && ((mInfoSdpRange->npt_start.npt_sec.milli_sec < mySdpRange->npt_start.npt_sec.milli_sec)))
797                         {
798                             mySdpRange->npt_start.npt_sec = mInfoSdpRange->npt_start.npt_sec;
799                         }
800                     }
801                     if (mInfoSdpRange->npt_end.npt_format == NptTimeFormat::NPT_SEC)
802                     {
803                         if (mInfoSdpRange->npt_end.npt_sec.sec > mySdpRange->npt_end.npt_sec.sec)
804                         {
805                             mySdpRange->npt_end.npt_sec = mInfoSdpRange->npt_end.npt_sec;
806                         }
807                         else if ((mInfoSdpRange->npt_end.npt_sec.sec == mySdpRange->npt_end.npt_sec.sec)
808                                  && ((mInfoSdpRange->npt_end.npt_sec.milli_sec > mySdpRange->npt_end.npt_sec.milli_sec)))
809                         {
810                             mySdpRange->npt_end.npt_sec = mInfoSdpRange->npt_end.npt_sec;
811                         }
812                     }
813                 }
814             }
815         }
816     }
817     return SDP_SUCCESS;
818 }
819 
820 OSCL_EXPORT_REF SDP_ERROR_CODE
parseSDPDownload(const char * sdpText,int length,SDPInfo * sdp,movieInfo * mv)821 SDP_Parser::parseSDPDownload(const char *sdpText,
822                              int length,
823                              SDPInfo *sdp,
824                              movieInfo *mv)
825 {
826     SDP_ERROR_CODE retval = parseSDP(sdpText, length, sdp);
827     if (retval != SDP_SUCCESS)
828     {
829         mv->trackCount = 0;
830         mv->movieName[0] = '\0';
831         mv->creationDate[0] = '\0';
832         return retval;
833     }
834     else
835     {
836         /*Get Movie name*/
837         int len = oscl_strlen(sdp->getSessionInfo()->getSessionName());
838         if (len >= MAX_STRING_LEN)
839         {
840             oscl_strncpy(mv->movieName, sdp->getSessionInfo()->getSessionName(), (MAX_STRING_LEN - 1));
841             mv->movieName[MAX_STRING_LEN-1] = '\0';
842         }
843         else
844         {
845             oscl_strncpy(mv->movieName, sdp->getSessionInfo()->getSessionName(), len);
846             mv->movieName[len] = '\0';
847         }
848 
849         /*Get creation date*/
850         len = oscl_strlen(sdp->getSessionInfo()->getCreationDate());
851         if (len >= MAX_STRING_LEN)
852         {
853             oscl_strncpy(mv->creationDate, sdp->getSessionInfo()->getCreationDate(), (MAX_STRING_LEN - 1));
854             mv->creationDate[MAX_STRING_LEN-1] = '\0';
855         }
856         else
857         {
858             oscl_strncpy(mv->creationDate, sdp->getSessionInfo()->getCreationDate(), len);
859             mv->creationDate[len] = '\0';
860         }
861 
862         /*Get number of tracks*/
863         mv->trackCount = sdp->getNumMediaObjects();
864 
865         /*Get start stop times*/
866         convertToMilliSec(*sdp->getSessionInfo()->getRange(), mv->duration.startTime, mv->duration.stopTime);
867 
868         /*Get MIMEType and other track info*/
869         for (int ii = 0; ii < mv->trackCount; ii++)
870         {
871             Oscl_Vector<mediaInfo*, SDPParserAlloc> mediaInfoVec =
872                 sdp->getMediaInfo(ii);
873 
874             /*
875              * There would only be one element in this vector
876              * for fast track download content.
877              */
878             mediaInfo* minfo = mediaInfoVec[0];
879 
880             mv->TrackArray[ii].bitrate = minfo->getBitrate();
881             len = oscl_strlen(minfo->getMIMEType());
882             if (len >= MAX_STRING_LEN)
883             {
884                 oscl_strncpy(mv->TrackArray[ii].codec_type,
885                              minfo->getMIMEType(),
886                              (MAX_STRING_LEN - 1));
887                 mv->TrackArray[ii].codec_type[MAX_STRING_LEN-1] = '\0';
888             }
889             else
890             {
891                 oscl_strncpy(mv->TrackArray[ii].codec_type,
892                              minfo->getMIMEType(),
893                              len);
894                 mv->TrackArray[ii].codec_type[len] = '\0';
895             }
896             const char *trackID = minfo->getControlURL();
897             int track = 0;
898             if (trackID != NULL)
899             {
900                 const char *locateID = oscl_strstr(trackID, "=");
901                 if (locateID != NULL)
902                 {
903                     locateID += 1;
904                     uint32 atoi_tmp;
905                     PV_atoi(locateID, 'd', atoi_tmp);
906                     track = atoi_tmp;
907                 }
908             }
909             mv->TrackArray[ii].trackID = track;
910         }
911     }
912     return SDP_SUCCESS;
913 }
914 
915 
916 int
convertToMilliSec(RtspRangeType range,int & startTime,int & stopTime)917 SDP_Parser::convertToMilliSec(RtspRangeType range , int &startTime, int &stopTime)
918 {
919     switch (range.format)
920     {
921         case RtspRangeType::NPT_RANGE:
922         {
923             if (range.start_is_set)
924             {
925                 switch (range.npt_start.npt_format)
926                 {
927                     case NptTimeFormat::NOW:
928                     {
929                         startTime = 0;
930                     }
931                     break;
932                     case NptTimeFormat::NPT_SEC:
933                     {
934                         startTime = (int)(1000 * ((float)range.npt_start.npt_sec.sec + range.npt_start.npt_sec.milli_sec));
935                     }
936                     break;
937                     case NptTimeFormat::NPT_HHMMSS:
938                     {
939                         startTime = 3600000 * range.npt_start.npt_hhmmss.hours + 60000 * range.npt_start.npt_hhmmss.min + 1000 * range.npt_start.npt_hhmmss.sec + (int)(10 * range.npt_start.npt_hhmmss.frac_sec);
940                     }
941                     break;
942                 }
943             }
944             else
945             {
946                 startTime = 0;
947             }
948             if (range.end_is_set)
949             {
950                 switch (range.npt_end.npt_format)
951                 {
952                     case NptTimeFormat::NOW:
953                     {
954                         stopTime = 0;
955                     }
956                     break;
957                     case NptTimeFormat::NPT_SEC:
958                     {
959                         stopTime = (int)(1000 * ((float)range.npt_end.npt_sec.sec + range.npt_end.npt_sec.milli_sec));
960                     }
961                     break;
962                     case NptTimeFormat::NPT_HHMMSS:
963                     {
964                         stopTime = 3600000 * range.npt_end.npt_hhmmss.hours + 60000 * range.npt_end.npt_hhmmss.min + 1000 * range.npt_end.npt_hhmmss.sec + (int)(100 * range.npt_end.npt_hhmmss.frac_sec);
965                     }
966                     break;
967                 }
968             }
969             else
970             {
971                 stopTime = false;
972             }
973         }
974         break;
975         case RtspRangeType::SMPTE_RANGE:
976         case RtspRangeType::SMPTE_25_RANGE:
977         case RtspRangeType::SMPTE_30_RANGE:
978         {
979             if (range.start_is_set)
980             {
981                 startTime = 3600000 * range.smpte_start.hours + 60000 * range.smpte_start.minutes + 1000 * range.smpte_start.seconds;
982             }
983             else
984             {
985                 startTime = 0;
986             }
987             if (range.end_is_set)
988             {
989                 stopTime = 3600000 * range.smpte_end.hours + 60000 * range.smpte_end.minutes + 1000 * range.smpte_end.seconds;
990             }
991             else
992             {
993                 stopTime = 0;
994             }
995         }
996         break;
997         case RtspRangeType::ABS_RANGE:
998         {
999             startTime = 0;
1000             stopTime = 0;
1001         }
1002         break;
1003         case RtspRangeType::UNKNOWN_RANGE:
1004         case RtspRangeType::INVALID_RANGE:
1005         {
1006             startTime = 0;
1007             stopTime = 0;
1008             return -1;
1009         }
1010         // break;   This statement was removed to avoid compiler warning for Unreachable Code
1011 
1012         default:
1013         {
1014             startTime = 0;
1015             stopTime = 0;
1016             return -1;
1017         }
1018         // break;   This statement was removed to avoid compiler warning for Unreachable Code
1019     }
1020     return 0;
1021 }
1022 
getNumberOfTracks()1023 OSCL_EXPORT_REF int SDP_Parser::getNumberOfTracks()
1024 {
1025     return mediaArrayIndex;
1026 }
1027 
setNumberOfTracks(int tracks)1028 OSCL_EXPORT_REF int SDP_Parser::setNumberOfTracks(int tracks)
1029 {
1030     return (mediaArrayIndex = tracks);
1031 }
1032 
1033 
1034