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