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 "aac_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 SDPAACMediaInfoParser::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 const char *current_start = buff; //Pointer to the beginning of the media text
32 const char *end = buff + index; //Pointer to the end of the media text
33 const char *line_start_ptr, *line_end_ptr;
34 int decLength = 0;
35 int fmtp_cnt = 0;
36 SDPAllocDestructDealloc<uint8> SDP_alloc;
37
38 while (get_next_line(current_start, end,
39 line_start_ptr, line_end_ptr))
40 {
41 if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
42 {
43 line_start_ptr += oscl_strlen("a=alt:");
44 for (; *line_start_ptr != ':'; line_start_ptr++);
45 line_start_ptr = line_start_ptr + 1;
46 }
47
48 if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
49 {
50
51 const char *tmp_start_line, *tmp_end_line;
52
53 fmtp_cnt++;
54
55 tmp_start_line = line_start_ptr + oscl_strlen("a=fmtp:");
56 tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
57 if (tmp_start_line >= line_end_ptr)
58 {
59 break;
60 }
61 tmp_end_line = skip_to_whitespace(tmp_start_line, line_end_ptr);
62 if (tmp_end_line < tmp_start_line)
63 {
64 break;
65 }
66 tmp_start_line = tmp_end_line + 1;
67 tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
68 if (tmp_start_line >= line_end_ptr)
69 {
70 break;
71 }
72 int ii = 0;
73 const char *temp = tmp_start_line;
74 for (ii = 0; ii < (line_end_ptr - tmp_start_line) ; ii++)
75 {
76 if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line - 1)))
77 {
78 tmp_end_line = tmp_start_line + ii;
79 if ((line_end_ptr - tmp_start_line - 1) == ii)
80 {
81 tmp_end_line++;
82 }
83
84 if (!oscl_strncmp(temp, "config=", oscl_strlen("config=")))
85 {
86 uint32 currentLength;
87 temp += oscl_strlen("config=");
88 temp = skip_whitespace(temp, line_end_ptr);
89 if (temp >= line_end_ptr)
90 {
91 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - no data in config= field"));
92 return SDP_BAD_MEDIA_FMTP;
93 }
94 currentLength = (int)(tmp_end_line - temp) / 2;
95
96 if (decLength < (int) currentLength)
97
98 decLength = currentLength;
99 }
100 if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
101 temp = skip_whitespace(temp, line_end_ptr);
102 if (temp >= line_end_ptr)
103 {
104 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - Format in a=fmtp line is incorrect"));
105 return SDP_BAD_MEDIA_FMTP;
106 }
107 }
108 }
109 }
110 current_start = line_end_ptr + 1;
111 }
112
113 if (fmtp_cnt == 0) // a=fmtp field not found
114 {
115 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp field not found"));
116 return SDP_FAILURE_NO_FMTP_FIELD;
117 }
118
119 bool altMedia = false;
120 if (!alt_id || (alt_def_id == true))
121 altMedia = false;
122 else
123 altMedia = true;
124
125 //Allocate media info class here
126 void *memory = sdp->alloc(sizeof(aac_mediaInfo), altMedia);
127 if (NULL == memory)
128 {
129 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - unable to allocate memory to media parser"));
130 return SDP_NO_MEMORY;
131 }
132 else
133 {
134 aac_mediaInfo *aacA = OSCL_PLACEMENT_NEW(memory, aac_mediaInfo());
135
136 aacA->setMediaInfoID(sdp->getMediaObjectIndex());
137
138 // Allocate memory to the payload specific objects
139 for (uint32 ii = 0; ii < payload_vec.size(); ii++)
140 {
141 void* mem = aacA->alloc(sizeof(AacPayloadSpecificInfoType));
142 if (mem == NULL)
143 {
144 return SDP_NO_MEMORY;
145 }
146 else
147 {
148 OSCL_PLACEMENT_NEW(mem, AacPayloadSpecificInfoType(payload_vec[ii]));
149 }
150 }
151
152
153 if (alt_id && !alt_def_id)
154 {
155 sdp->copyFmDefMedia(aacA);
156 aacA->resetAlternateTrackId();
157 aacA->resetDependentTrackId();
158 }
159
160 SDP_ERROR_CODE status = baseMediaInfoParser(buff, aacA, index, alt_id, alt_def_id, isSipSdp);
161 if (status != SDP_SUCCESS)
162 {
163 return status;
164 }
165
166
167 current_start = buff;
168
169 while (get_next_line(current_start, end,
170 line_start_ptr, line_end_ptr))
171 {
172 switch (*line_start_ptr)
173 {
174 case 'a':
175 {
176 const char *sptr;
177 if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
178 {
179 line_start_ptr += oscl_strlen("a=alt:");
180 for (; *line_start_ptr != ':'; line_start_ptr++);
181 line_start_ptr = line_start_ptr + 1;
182 }
183 if (!oscl_strncmp(line_start_ptr, "a=lang:", oscl_strlen("a=lang:")))
184 {
185 sptr = line_start_ptr + oscl_strlen("a=lang:");
186 sptr = skip_whitespace(sptr, line_end_ptr);
187 if (sptr >= line_end_ptr)
188 {
189 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=lang field incorrect"));
190 return SDP_BAD_MEDIA_LANG_FIELD;
191 }
192 OsclMemoryFragment memFrag;
193 memFrag.ptr = (void*)sptr;
194 memFrag.len = (line_end_ptr - sptr);
195
196 ((aac_mediaInfo*)aacA)->setLang(memFrag);
197 }
198 if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
199 {
200 const char *tmp_start_line, *tmp_end_line;
201 tmp_start_line = line_start_ptr + oscl_strlen("a=fmtp:");
202 tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
203 if (tmp_start_line >= line_end_ptr)
204 {
205 break;
206 }
207 tmp_end_line = skip_to_whitespace(tmp_start_line, line_end_ptr);
208 if (tmp_end_line < tmp_start_line)
209 {
210 break;
211 }
212 uint32 payloadNumber;
213 if (PV_atoi(tmp_start_line, 'd', (tmp_end_line - tmp_start_line), payloadNumber) == false)
214 {
215 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect"));
216 return SDP_BAD_MEDIA_FMTP;
217 }
218 else
219 {
220 int p;
221 if (!aacA->lookupPayloadNumber(payloadNumber, p))
222 {
223 fmtp_cnt--;
224 break;
225 }
226 }
227 // payloadNumber is present in the mediaInfo. get the payload
228 // Specific pointer corresponding to this payload
229 AacPayloadSpecificInfoType* payloadPtr =
230 (AacPayloadSpecificInfoType*)aacA->getPayloadSpecificInfoTypePtr(payloadNumber);
231
232 PVMF_SDP_PARSER_LOGINFO((0, "SDPAacMediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNumber));
233
234 tmp_start_line = tmp_end_line + 1;
235 tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
236 if (tmp_start_line >= line_end_ptr)
237 {
238 break;
239 }
240 int ii = 0;
241 const char *temp = tmp_start_line;
242 for (ii = 0; ii < (line_end_ptr - tmp_start_line) ; ii++)
243 {
244 if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line - 1)))
245 {
246 tmp_end_line = tmp_start_line + ii;
247 if (ii == (line_end_ptr - tmp_start_line - 1))
248 {
249 tmp_end_line += 1;
250 }
251
252 if (!oscl_strncmp(temp, "config=", oscl_strlen("config=")))
253 {
254
255 uint8 *mptr = SDP_alloc.allocate(decLength);
256 OsclRefCounterSA< SDPAllocDestructDealloc<uint8> > *refcnt = new OsclRefCounterSA< SDPAllocDestructDealloc<uint8> >(mptr);
257 OsclSharedPtr<uint8> decInfo(mptr, refcnt);
258
259 temp += oscl_strlen("config=");
260 temp = skip_whitespace(temp, line_end_ptr);
261 if (temp >= line_end_ptr)
262 {
263 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for config= field"));
264 return SDP_BAD_MEDIA_FMTP;
265 }
266 decLength = (int)(tmp_end_line - temp) / 2;
267 int idx = 0;
268 for (idx = 0; idx < decLength; idx++)
269 {
270 uint32 val;
271 if (PV_atoi((temp + 2*idx), 'x', 2, val) == false)
272 {
273 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for config= field"));
274 return SDP_BAD_MEDIA_FMTP;
275 }
276
277 *(decInfo + idx) = (uint8) val;
278 }
279
280 if (payloadPtr)
281 {
282 payloadPtr->setDecoderSpecificInfo(decInfo);
283 payloadPtr->setDecoderSpecificInfoSize(decLength);
284 }
285 else
286 {
287 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for payload"));
288 return SDP_PAYLOAD_MISMATCH;
289 }
290 }
291
292 // add code for cpresent flag
293 if (!oscl_strncmp(temp, "cpresent=", oscl_strlen("cpresent=")))
294 {
295 temp += oscl_strlen("cpresent=");
296 temp = skip_whitespace(temp, line_end_ptr);
297 if (temp > line_end_ptr)
298 {
299 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp format is incorrect for cpresent= field"));
300 return SDP_BAD_MEDIA_FMTP;
301 }
302 uint32 cpresent; //Assuming that the possible values are either 0 or 1
303 if (PV_atoi(temp, 'd', tmp_end_line - temp, cpresent) == true)
304 {
305 if (payloadPtr)
306 payloadPtr->setcpresent(cpresent ? true : false);
307 else
308 return SDP_PAYLOAD_MISMATCH;
309 }
310 }
311 if (!oscl_strncmp(temp, "SBR-enabled=", oscl_strlen("SBR-enabled=")))
312 {
313 temp += oscl_strlen("SBR-enabled=");
314 temp = skip_whitespace(temp, line_end_ptr);
315 if (temp > line_end_ptr)
316 {
317 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp format is incorrect for SBR-enabled= field"));
318 return SDP_BAD_MEDIA_FORMAT;
319 }
320 uint32 sbrEn; //Assuming that the possible values are either 0 or 1
321 if (PV_atoi(temp, 'd', tmp_end_line - temp, sbrEn) == true)
322 {
323 if (payloadPtr)
324 payloadPtr->setAACplusSBRenabled(sbrEn ? true : false);
325 else
326 return SDP_PAYLOAD_MISMATCH;
327 }
328 }
329
330
331 if (!oscl_strncmp(temp, "decode_buf=", oscl_strlen("decode_buf=")))
332 {
333 temp += oscl_strlen("decode_buf=");
334 temp = skip_whitespace(temp, tmp_end_line);
335 if (temp > tmp_end_line)
336 {
337 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp format is incorrect for decode_buf= field"));
338 return SDP_BAD_MEDIA_FORMAT;
339 }
340 uint32 dec;
341 if (PV_atoi(temp, 'd', tmp_end_line - temp, dec) == true)
342 {
343 if (payloadPtr)
344 payloadPtr->setMaxBufferSize(dec);
345 else
346 return SDP_PAYLOAD_MISMATCH;
347 }
348 }
349
350 if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
351 temp = skip_whitespace(temp, line_end_ptr);
352 if (temp >= line_end_ptr)
353 {
354 PVMF_SDP_PARSER_LOGERROR((0, "SDPAACMediaInfoParser::parseMediaInfo - a=fmtp format is bad"));
355 return SDP_BAD_MEDIA_FORMAT;
356 }
357 }
358 }
359 }
360 }
361 break;
362 default:
363 break;
364 }
365 current_start = line_end_ptr;
366 }
367
368
369 sessionDescription *session = sdp->getSessionInfo();
370
371 const char *altGroupBW = session->getAltGroupBW();
372 int length = session->getAltGroupBWLength();
373
374 if (length > 0)
375 {
376 status = setDependentMediaId(altGroupBW, length, aacA, alt_id);
377 if (status != SDP_SUCCESS)
378 return SDP_BAD_MEDIA_ALT_ID;
379 }
380
381 const char *altGroupLANG = session->getAltGroupLANG();
382 length = session->getAltGroupLANGLength();
383
384 if (length > 0)
385 {
386 status = setDependentMediaId(altGroupLANG, length, aacA, alt_id);
387 if (status != SDP_SUCCESS)
388 return SDP_BAD_MEDIA_ALT_ID;
389 }
390
391 if (aacA->getCFieldStatus() || session->getCFieldStatus())
392 {
393 //if sample rate is zero override with defaults
394 Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadSpecificInfoVector =
395 aacA->getPayloadSpecificInfoVector();
396 for (int ii = 0; ii < (int)payloadSpecificInfoVector.size(); ii++)
397 {
398 if (payloadSpecificInfoVector[ii]->getSampleRate() == 0)
399 {
400 payloadSpecificInfoVector[ii]->sampleRate =
401 PVMF_SDP_DEFAULT_LATM_SAMPLE_RATE;
402 }
403 }
404 return SDP_SUCCESS;
405 }
406 else
407 {
408 return SDP_FAILURE_NO_C_FIELD;
409 }
410 }
411 }
412
413