Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #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 
     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 
     52 OSCL_EXPORT_REF SDP_Parser::~SDP_Parser()
     53 {
     54 }
     55 
     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 
    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
    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
    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
    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 
   1023 OSCL_EXPORT_REF int SDP_Parser::getNumberOfTracks()
   1024 {
   1025     return mediaArrayIndex;
   1026 }
   1027 
   1028 OSCL_EXPORT_REF int SDP_Parser::setNumberOfTracks(int tracks)
   1029 {
   1030     return (mediaArrayIndex = tracks);
   1031 }
   1032 
   1033 
   1034