• 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 "amr_media_info_parser.h"
19 #include "oscl_string_utils.h"
20 #include "oscl_string_containers.h"
21 
22 SDP_ERROR_CODE
parseMediaInfo(const char * buff,const int index,SDPInfo * sdp,payloadVector payload_vec,bool isSipSdp,int alt_id,bool alt_def_id)23 SDPAMRMediaInfoParser::parseMediaInfo(const char *buff,
24                                       const int index,
25                                       SDPInfo *sdp,
26                                       payloadVector payload_vec,
27                                       bool isSipSdp,
28                                       int alt_id,
29                                       bool alt_def_id)
30 {
31 
32     const char *current_start = buff; //Pointer to the beginning of the media text
33     const char *end = buff + index;   //Pointer to the end of the media text
34     const char *line_start_ptr, *line_end_ptr;
35     int modes[] = {1, 2, 4, 8, 16, 32, 64, 128};
36 
37     int fmtp_cnt = 0;
38 
39     bool altMedia = false;
40     if (!alt_id || (alt_def_id == true))
41         altMedia = false;
42     else
43         altMedia = true;
44     void *memory = NULL;
45 
46     memory = sdp->alloc(sizeof(amr_mediaInfo), altMedia);
47 
48     if (NULL == memory)
49     {
50         PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - No Memory allocated"));
51         return SDP_NO_MEMORY;
52     }
53     else
54     {
55         amr_mediaInfo *amrA = OSCL_PLACEMENT_NEW(memory, amr_mediaInfo());
56 
57         amrA->setMediaInfoID(sdp->getMediaObjectIndex());
58 
59         // Allocate memory to the payload specific objects
60         for (uint32 ii = 0; ii < payload_vec.size(); ii++)
61         {
62             void* mem = amrA->alloc(sizeof(AmrPayloadSpecificInfoType));
63             if (mem == NULL)
64             {
65                 return SDP_NO_MEMORY;
66             }
67             else
68             {
69                 AmrPayloadSpecificInfoType* amrPayload = OSCL_PLACEMENT_NEW(mem, AmrPayloadSpecificInfoType(payload_vec[ii]));
70                 (void) amrPayload;
71             }
72         }
73 
74         if (alt_id && !alt_def_id)
75         {
76             sdp->copyFmDefMedia(amrA);
77             //empty alternate & default track ID vectors.
78             amrA->resetAlternateTrackId();
79             amrA->resetDependentTrackId();
80         }
81 
82         SDP_ERROR_CODE status = baseMediaInfoParser(buff, amrA, index , alt_id, alt_def_id, isSipSdp);
83 
84         if (status != SDP_SUCCESS)
85         {
86             return status;
87         }
88 
89         while (get_next_line(current_start, end,
90                              line_start_ptr, line_end_ptr))
91         {
92             switch (*line_start_ptr)
93             {
94                 case 'a':
95                 {
96                     const char *sptr;
97                     if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
98                     {
99                         line_start_ptr += oscl_strlen("a=alt:");
100                         for (; *line_start_ptr != ':'; line_start_ptr++);
101                         line_start_ptr = line_start_ptr + 1;
102                     }
103                     if (!oscl_strncmp(line_start_ptr, "a=lang:", oscl_strlen("a=lang:")))
104                     {
105                         sptr = line_start_ptr + oscl_strlen("a=lang:");
106                         sptr = skip_whitespace(sptr, line_end_ptr);
107                         if (sptr >= line_end_ptr)
108                         {
109                             PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=lang field bad"));
110                             return SDP_BAD_MEDIA_LANG_FIELD;
111                         }
112                         OsclMemoryFragment memFrag;
113                         memFrag.ptr = (void*)sptr;
114                         memFrag.len = (line_end_ptr - sptr);
115 
116                         ((amr_mediaInfo*)amrA)->setLang(memFrag);
117                     }
118 
119                     if (!oscl_strncmp(line_start_ptr, "a=maxptime:", oscl_strlen("a=maxptime:")))
120                     {
121                         sptr = line_start_ptr + oscl_strlen("a=maxptime:");
122                         sptr = skip_whitespace(sptr, line_end_ptr);
123                         if (sptr >= line_end_ptr)
124                         {
125                             PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=maxptime field bad"));
126                             return SDP_BAD_MEDIA_MAXPTIME;
127                         }
128                         uint32 maxptime = 0;
129                         if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), maxptime) == true)
130                         {
131                             ((amr_mediaInfo*)amrA)->setMaximumPTime(maxptime);
132                         }
133                     }
134                     if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
135                     {
136                         const char *tmp_start_line, *tmp_end_line;
137 
138                         fmtp_cnt++;
139 
140                         tmp_start_line = line_start_ptr + oscl_strlen("a=fmtp:");
141                         tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
142                         if (tmp_start_line >= line_end_ptr)
143                         {
144                             break;
145                         }
146                         tmp_end_line = skip_to_whitespace(tmp_start_line, line_end_ptr);
147                         if (tmp_end_line < tmp_start_line)
148                         {
149                             break;
150                         }
151                         uint32 payloadNumber;
152                         if (PV_atoi(tmp_start_line, 'd', (tmp_end_line - tmp_start_line), payloadNumber) == false)
153                         {
154                             PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field bad for payload number"));
155                             return SDP_BAD_MEDIA_FMTP;
156                         }
157                         else
158                         {
159                             int p;
160                             if (!amrA->lookupPayloadNumber(payloadNumber, p))
161                             {
162                                 fmtp_cnt--;
163                                 break;
164                             }
165                         }
166 
167                         // payloadNumber is present in the mediaInfo. get the payload
168                         // Specific pointer corresponding to this payload
169                         AmrPayloadSpecificInfoType* payloadPtr =
170                             (AmrPayloadSpecificInfoType*)amrA->getPayloadSpecificInfoTypePtr(payloadNumber);
171                         if (payloadPtr == NULL)
172                         {
173                             PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - unable to find payload ptr for payload number"));
174                             return SDP_PAYLOAD_MISMATCH;
175                         }
176 
177                         PVMF_SDP_PARSER_LOGINFO((0, "SDPAmrMediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNumber));
178 
179                         tmp_start_line = tmp_end_line + 1;
180                         tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
181                         if (tmp_start_line >= line_end_ptr)
182                         {
183                             break;
184                         }
185                         int ii = 0;
186                         const char *temp = tmp_start_line;
187                         for (ii = 0; ii < (line_end_ptr - tmp_start_line); ii++)
188                         {
189                             if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line) - 1))
190                             {
191                                 tmp_end_line = tmp_start_line + ii;
192                                 if (ii == (line_end_ptr - tmp_start_line) - 1)
193                                 {
194                                     tmp_end_line += 1;
195                                 }
196                                 if (!oscl_strncmp(temp, "maxptime=", oscl_strlen("maxptime=")))
197                                 {
198                                     temp += oscl_strlen("maxptime=");
199                                     temp = skip_whitespace(temp, tmp_end_line);
200                                     if (temp >= tmp_end_line)
201                                     {
202                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for maxptime="));
203                                         return SDP_BAD_MEDIA_MAXPTIME;
204                                     }
205                                     uint32 maxPTime;
206                                     if (PV_atoi(temp, 'd', (tmp_end_line - temp),  maxPTime) == true)
207                                         payloadPtr->setMaximumPTime(maxPTime);
208                                 }
209                                 if (!oscl_strncmp(temp, "crc", oscl_strlen("crc")))
210                                 {
211                                     if (!oscl_strncmp(temp, "crc=0", oscl_strlen("crc=0")))
212                                         payloadPtr->setCRC(false);
213                                     else
214                                         payloadPtr->setCRC(true);
215 
216                                 }
217                                 if (!oscl_strncmp(temp, "robust-sorting", oscl_strlen("robust-sorting")))
218                                 {
219 
220 
221                                     //We need to make sure that we do not read beyond valid memory
222                                     if ((line_end_ptr - temp) >= (int)oscl_strlen("robust-sorting=0"))
223                                     {
224                                         if (oscl_strncmp(temp, "robust-sorting=0", oscl_strlen("robust-sorting=0")))
225                                         {
226                                             payloadPtr->setRobustSorting(true);
227                                         }
228                                     }
229                                     else
230                                     {
231                                         payloadPtr->setRobustSorting(false);
232                                     }
233                                 }
234                                 if (!oscl_strncmp(temp, "octet-align", oscl_strlen("octet-align")))
235                                 {
236 
237                                     //We need to make sure that we do not read beyond valid memory
238                                     if ((line_end_ptr - temp) >= (int) oscl_strlen("octet-align=0"))
239                                     {
240                                         if (oscl_strncmp(temp, "octet-align=0", oscl_strlen("octet-align=0")))
241                                         {
242                                             payloadPtr->setOctetAlign(true);
243                                         }
244                                     }
245                                     else
246                                     {
247                                         payloadPtr->setOctetAlign(false);
248                                     }
249                                 }
250                                 if (!oscl_strncmp(temp, "interleaving=", oscl_strlen("interleaving=")))
251                                 {
252                                     temp += oscl_strlen("interleaving=");
253                                     temp = (char *)skip_whitespace(temp, tmp_end_line);
254                                     if (temp > tmp_end_line)
255                                     {
256                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for interleaving="));
257                                         return SDP_BAD_MEDIA_FMTP;
258                                     }
259                                     uint32 interleave;
260                                     if (PV_atoi(temp, 'd', (tmp_end_line - temp),   interleave) == true)
261                                         payloadPtr->setInterLeaving(interleave);
262                                 }
263                                 if (!oscl_strncmp(temp, "decode_buf=", oscl_strlen("decode_buf=")))
264                                 {
265                                     temp += oscl_strlen("decode_buf=");
266                                     temp = skip_whitespace(temp, tmp_end_line);
267                                     if (temp > tmp_end_line)
268                                     {
269                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for decode_buf="));
270                                         return SDP_BAD_MEDIA_FMTP;
271                                     }
272                                     uint32 dec;
273                                     if (PV_atoi(temp, 'd', (tmp_end_line - temp),   dec) == true)
274                                         payloadPtr->setMaxBufferSize(dec);
275                                 }
276                                 if (!oscl_strncmp(temp, "mode-change-period=", oscl_strlen("mode-change-period=")))
277                                 {
278                                     temp += oscl_strlen("mode-change-period=");
279                                     temp = skip_whitespace(temp, tmp_end_line);
280                                     if (temp > tmp_end_line)
281                                     {
282                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for mode-change-period="));
283                                         return SDP_BAD_MEDIA_FMTP;
284                                     }
285                                     uint32 mcp;
286                                     if (PV_atoi(temp, 'd', (tmp_end_line - temp),  mcp) == true)
287                                         payloadPtr->setModeChangePeriod(mcp);
288                                 }
289                                 if (!oscl_strncmp(temp, "mode-change-neighbor", oscl_strlen("mode-change-neighbor")))
290                                 {
291                                     //We need to make sure that we do not read beyond valid memory
292                                     if ((line_end_ptr - temp) >= (int)oscl_strlen("mode-change-neighbor=0"))
293                                     {
294                                         if (oscl_strncmp(temp, "mode-change-neighbor=0", oscl_strlen("mode-change-neighbor=0")))
295                                         {
296                                             payloadPtr->setModeChangeNeighbor(true);
297                                         }
298                                     }
299                                     else
300                                     {
301                                         payloadPtr->setModeChangeNeighbor(false);
302                                     }
303                                 }
304                                 if (!oscl_strncmp(temp, "mode-change-neighbor=1", oscl_strlen("mode-change-neighbor=1")))
305                                 {
306                                     payloadPtr->setModeChangeNeighbor(true);
307                                 }
308                                 if (!oscl_strncmp(temp, "mode-set=", oscl_strlen("mode-set=")))
309                                 {
310                                     temp += oscl_strlen("mode-set=");
311                                     temp = skip_whitespace(temp, tmp_end_line);
312                                     if (temp > tmp_end_line)
313                                     {
314                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for mode-set="));
315                                         return SDP_BAD_MEDIA_FMTP;
316                                     }
317                                     int idx = 0;
318                                     int cModeList = 0;
319                                     const char *begin = temp, *end;
320                                     for (idx = 0; idx < (tmp_end_line - temp); idx++)
321                                     {
322                                         if ((temp[idx] == ',') || ((tmp_end_line - temp) - 1 == idx))
323                                         {
324                                             {
325                                                 end = temp + idx;
326                                             }
327                                             if ((tmp_end_line - temp) - 1 == idx)
328                                             {
329                                                 end++;
330                                             }
331                                             uint32 temp_idx;
332                                             if (PV_atoi(begin, 'd', (end - begin),  temp_idx) == true) cModeList += modes[temp_idx];
333                                             begin = end + 1;
334                                         }
335                                     }
336                                     payloadPtr->setCodecModeList(cModeList);
337                                 }
338                                 if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
339                                 temp = skip_whitespace(temp, line_end_ptr);
340                                 if (temp >= line_end_ptr)
341                                 {
342                                     PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad"));
343                                     return SDP_BAD_MEDIA_FMTP;
344                                 }
345                             }
346                         }
347                     }
348                 }
349                 break;
350                 default:
351                     break;
352             }
353             current_start = line_end_ptr;
354         }
355         sessionDescription *session = sdp->getSessionInfo();
356 
357         if (fmtp_cnt != amrA->getMediaPayloadNumberCount() && isSipSdp == false)
358             return SDP_PAYLOAD_MISMATCH;
359 
360         const char *altGroupBW = session->getAltGroupBW();
361         int length = session->getAltGroupBWLength();
362 
363         if (length > 0)
364         {
365             status = setDependentMediaId(altGroupBW, length, amrA, alt_id);
366             if (status != SDP_SUCCESS)
367                 return SDP_BAD_MEDIA_ALT_ID;
368         }
369 
370         const char *altGroupLANG = session->getAltGroupLANG();
371         length = session->getAltGroupLANGLength();
372 
373         if (length > 0)
374         {
375             status = setDependentMediaId(altGroupLANG, length, amrA, alt_id);
376             if (status != SDP_SUCCESS)
377                 return SDP_BAD_MEDIA_ALT_ID;
378         }
379 
380         if (amrA->getCFieldStatus() || session->getCFieldStatus())
381         {
382             //if sample rate is zero override with defaults
383             Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadSpecificInfoVector =
384                 amrA->getPayloadSpecificInfoVector();
385             for (int ii = 0; ii < (int)payloadSpecificInfoVector.size(); ii++)
386             {
387                 if (payloadSpecificInfoVector[ii]->getSampleRate() == 0)
388                 {
389                     payloadSpecificInfoVector[ii]->sampleRate =
390                         PVMF_SDP_DEFAULT_AMR_SAMPLE_RATE;
391                 }
392             }
393             return SDP_SUCCESS;
394         }
395         else
396         {
397             return SDP_FAILURE_NO_C_FIELD;
398         }
399     }
400 }
401