• 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 "m4v_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 SDPMPEG4MediaInfoParser::parseMediaInfo(const char *buff, const int index, SDPInfo *sdp, payloadVector payload_vec, bool isSipSdp, int alt_id, bool alt_def_id)
24 {
25 
26     const char *current_start = buff; //Pointer to the beginning of the media text
27     const char *end = buff + index;   //Pointer to the end of the media text
28     const char *line_start_ptr, *line_end_ptr;
29     int VOLLength = 0;
30     int fmtp_cnt = 0 ;
31     bool framesize_found_in_fmtp = false;
32     SDPAllocDestructDealloc<uint8> SDP_alloc;
33 
34 
35     while (get_next_line(current_start, end,
36                          line_start_ptr, line_end_ptr))
37     {
38         if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
39         {
40             line_start_ptr += oscl_strlen("a=alt:");
41             for (; *line_start_ptr != ':'; line_start_ptr++);
42             line_start_ptr = line_start_ptr + 1;
43         }
44         if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
45         {
46             char *tmp_start_line, *tmp_end_line;
47             fmtp_cnt++ ;
48 
49             tmp_start_line = (char *)line_start_ptr + oscl_strlen("a=fmtp:");
50             tmp_start_line = (char *)skip_whitespace(tmp_start_line, line_end_ptr);
51             if (tmp_start_line >= line_end_ptr)
52             {
53                 break;
54             }
55             tmp_end_line = (char *)skip_to_whitespace(tmp_start_line, line_end_ptr);
56             if (tmp_end_line < tmp_start_line)
57             {
58                 break;
59             }
60             tmp_start_line = tmp_end_line + 1;
61             tmp_start_line = (char *)skip_whitespace(tmp_start_line, line_end_ptr);
62             if (tmp_start_line >= line_end_ptr)
63             {
64                 break;
65             }
66             int ii = 0;
67             const char *temp = tmp_start_line;
68             for (ii = 0; ii < (line_end_ptr - tmp_start_line) ; ii++)
69             {
70                 if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line - 1)))
71                 {
72                     tmp_end_line = tmp_start_line + ii;
73                     if ((line_end_ptr - tmp_start_line - 1) == ii)
74                     {
75                         tmp_end_line++;
76                     }
77                     if (!oscl_strncmp(temp, "config=", oscl_strlen("config=")))
78                     {
79                         int currentVOLLength;
80                         temp += oscl_strlen("config=");
81                         temp = skip_whitespace(temp, line_end_ptr);
82                         if (temp >= line_end_ptr)
83                         {
84                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad config field"));
85                             return SDP_BAD_MEDIA_FMTP;
86                         }
87 
88                         currentVOLLength = (int)(tmp_end_line - temp) / 2;
89                         if (VOLLength < currentVOLLength)
90                             VOLLength = currentVOLLength;
91                     }
92                     if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
93                     temp = skip_whitespace(temp, line_end_ptr);
94                     if (temp >= line_end_ptr)
95                     {
96                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format"));
97                         return SDP_BAD_MEDIA_FMTP;
98                     }
99 
100                 }
101             }
102         }
103 
104 
105         current_start = line_end_ptr + 1;
106     }
107 
108     if (fmtp_cnt == 0 && isSipSdp == false)
109     {
110         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - No fmtp line found"));
111         return SDP_BAD_MEDIA_FORMAT;
112     }
113 
114     if (VOLLength < 0)
115     {
116         VOLLength = 0;
117     }
118 
119     bool altMedia = false;
120     if (!alt_id || (alt_def_id == true))
121         altMedia = false;
122     else
123         altMedia = true;
124 
125     void *memory = sdp->alloc(sizeof(m4v_mediaInfo), altMedia);
126     if (NULL == memory)
127     {
128         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - memory allocation failure"));
129         return SDP_NO_MEMORY;
130     }
131     else
132     {
133         m4v_mediaInfo *m4Video = OSCL_PLACEMENT_NEW(memory, m4v_mediaInfo());
134 
135         m4Video->setMediaInfoID(sdp->getMediaObjectIndex());
136 
137         // Allocate memory to the payload specific objects
138         for (uint32 ii = 0; ii < payload_vec.size(); ii++)
139         {
140             void* mem = m4Video->alloc(sizeof(M4vPayloadSpecificInfoType));
141             if (mem == NULL)
142             {
143                 PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Memory allocation failure"));
144                 return SDP_NO_MEMORY;
145             }
146             else
147             {
148                 M4vPayloadSpecificInfoType* payload = OSCL_PLACEMENT_NEW(mem, M4vPayloadSpecificInfoType(payload_vec[ii]));
149                 (void) payload;
150             }
151         }
152 
153 
154         if (alt_id && !alt_def_id)
155         {
156             sdp->copyFmDefMedia(m4Video);
157             //empty alternate & default track ID vectors.
158             m4Video->resetAlternateTrackId();
159             m4Video->resetDependentTrackId();
160         }
161 
162         SDP_ERROR_CODE status = baseMediaInfoParser(buff, m4Video, index, alt_id, alt_def_id, isSipSdp);
163         if (status != SDP_SUCCESS)
164         {
165             return status;
166         }
167 
168         current_start = buff;
169 
170 
171         while (get_next_line(current_start, end,
172                              line_start_ptr, line_end_ptr))
173         {
174             switch (*line_start_ptr)
175             {
176                 case 'a':
177                 {
178                     const char *sptr;
179                     if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false))
180                     {
181                         line_start_ptr += oscl_strlen("a=alt:");
182                         for (; *line_start_ptr != ':'; line_start_ptr++);
183                         line_start_ptr = line_start_ptr + 1;
184                     }
185                     if (!oscl_strncmp(line_start_ptr, "a=framerate:", oscl_strlen("a=framerate:")))
186                     {
187                         sptr = line_start_ptr + oscl_strlen("a=framerate:");
188                         sptr = skip_whitespace(sptr, line_end_ptr);
189                         if (sptr >= line_end_ptr)
190                         {
191                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=framerate line format"));
192                             return SDP_BAD_MEDIA_FRAME_RATE;
193                         }
194                         OsclFloat rate;
195                         if (!PV_atof(sptr, line_end_ptr - sptr, rate))
196                             return SDP_BAD_MEDIA_FORMAT;
197                         ((m4v_mediaInfo *)m4Video)->setFrameRate(rate);
198                     }
199                     if (!oscl_strncmp(line_start_ptr, "a=I_frame_interval:", oscl_strlen("a=I_frame_interval:")))
200                     {
201                         sptr = line_start_ptr + oscl_strlen("a=I_frame_interval:");
202                         sptr = skip_whitespace(sptr, line_end_ptr);
203                         if (sptr >= line_end_ptr)
204                         {
205                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=I_frame_interval line format"));
206                             return SDP_BAD_MEDIA_FRAME_INTERVAL;
207                         }
208                         uint32 ifi;
209                         if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), ifi) == true)((m4v_mediaInfo *)m4Video)->setIFrameInterval(ifi);
210                     }
211                     if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:")))
212                     {
213                         const char *tmp_start_line, *tmp_end_line;
214                         tmp_start_line = line_start_ptr + oscl_strlen("a=fmtp:");
215                         tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
216                         if (tmp_start_line >= line_end_ptr)
217                         {
218                             break;
219                         }
220                         tmp_end_line = skip_to_whitespace(tmp_start_line, line_end_ptr);
221                         if (tmp_end_line < tmp_start_line)
222                         {
223                             break;
224                         }
225                         uint32 payloadNumber;
226                         if (PV_atoi(tmp_start_line, 'd', (tmp_end_line - tmp_start_line), payloadNumber) == false)
227                         {
228                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad payload number"));
229                             return SDP_BAD_MEDIA_FMTP;
230                         }
231                         else
232                         {
233                             int p;
234                             if (!m4Video->lookupPayloadNumber(payloadNumber, p))
235                             {
236                                 fmtp_cnt--;
237                                 break;
238                             }
239                         }
240 
241                         M4vPayloadSpecificInfoType* payloadPtr =
242                             (M4vPayloadSpecificInfoType*)m4Video->getPayloadSpecificInfoTypePtr(payloadNumber);
243                         if (payloadPtr == NULL)
244                         {
245                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - payload pointer not found for payload"));
246                             return SDP_PAYLOAD_MISMATCH;
247                         }
248 
249                         PVMF_SDP_PARSER_LOGINFO((0, "SDPM4VMediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNumber));
250 
251                         tmp_start_line = tmp_end_line + 1;
252                         tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr);
253                         if (tmp_start_line >= line_end_ptr)
254                         {
255                             break;
256                         }
257                         int ii = 0;
258                         const char *temp = tmp_start_line;
259                         for (ii = 0; ii < (line_end_ptr - tmp_start_line) ; ii++)
260                         {
261                             if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line - 1)))
262                             {
263                                 tmp_end_line = tmp_start_line + ii;
264                                 if (ii == (line_end_ptr - tmp_start_line - 1))
265                                 {
266                                     tmp_end_line += 1;
267                                 }
268                                 if (!oscl_strncmp(temp, "config=", oscl_strlen("config=")))
269                                 {
270                                     uint8 *mptr = SDP_alloc.allocate(VOLLength);
271                                     OsclRefCounterSA< SDPAllocDestructDealloc<uint8> > *refcnt = new OsclRefCounterSA< SDPAllocDestructDealloc<uint8> >(mptr);
272                                     OsclSharedPtr<uint8> VOLPtr(mptr, refcnt);
273 
274                                     temp += oscl_strlen("config=");
275                                     temp = skip_whitespace(temp, line_end_ptr);
276                                     if (temp >= line_end_ptr)
277                                     {
278                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad config field"));
279                                         return SDP_BAD_MEDIA_FMTP;
280                                     }
281                                     VOLLength = (int)(tmp_end_line - temp) / 2;
282                                     int idx = 0;
283                                     for (idx = 0; idx < VOLLength; idx++)
284                                     {
285                                         uint32 val;
286                                         //Set this value in the vol header array
287                                         if (PV_atoi((temp + 2*idx), 'x', 2 , val) == false)
288                                         {
289                                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad config field"));
290                                             return SDP_BAD_MEDIA_FMTP;
291                                         }
292 
293                                         *(VOLPtr + idx) = (uint8)val;
294 
295                                     }
296 
297                                     payloadPtr->setVOLHeader(VOLPtr);
298                                     payloadPtr->setVOLHeaderSize(VOLLength);
299                                     payloadPtr->setDecoderSpecificInfo(VOLPtr);
300                                     payloadPtr->setDecoderSpecificInfoSize(VOLLength);
301 
302                                 }
303                                 if (!oscl_strncmp(temp, "profile-level-id=", oscl_strlen("profile-level-id=")))
304                                 {
305                                     temp += oscl_strlen("profile-level-id=");
306                                     temp = skip_whitespace(temp, line_end_ptr);
307                                     if (temp > line_end_ptr)
308                                     {
309                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad profile-level-id field"));
310                                         return SDP_BAD_MEDIA_FMTP;
311                                     }
312                                     uint32 pl;
313                                     if (PV_atoi(temp, 'd', tmp_end_line - temp ,  pl) == true)
314                                         payloadPtr->setProfileLevelID(pl);
315 
316                                 }
317                                 if (!oscl_strncmp(temp, "framesize=", oscl_strlen("framesize=")))
318                                 {
319                                     temp += oscl_strlen("framesize=");
320                                     temp = skip_whitespace(temp, tmp_end_line);
321                                     framesize_found_in_fmtp  = true;
322                                     if (temp > tmp_end_line)
323                                     {
324                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad framesize field"));
325                                         return SDP_BAD_MEDIA_FMTP;
326                                     }
327                                     const char *end = NULL;
328                                     int idx = 0;
329                                     for (idx = 0; idx < (tmp_end_line - temp); idx++)
330                                     {
331                                         if (temp[idx] == '-')
332                                         {
333                                             end = temp + idx;
334                                         }
335                                     }
336                                     if (end == NULL)
337                                     {
338                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - framesize width info missing"));
339                                         return SDP_MISSING_MEDIA_DESCRIPTION;
340                                     }
341                                     uint32 width;
342                                     if (PV_atoi(temp, 'd', (end - temp),  width) == true)
343                                         payloadPtr->setFrameWidth(width);
344                                     temp = end + 1;
345                                     temp = skip_whitespace(temp, tmp_end_line);
346                                     if (temp > tmp_end_line)
347                                     {
348                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - framesize height info missing"));
349                                         return SDP_BAD_MEDIA_FMTP;
350                                     }
351                                     uint32 height;
352                                     if (PV_atoi(temp, 'd', tmp_end_line - temp, height) == true)
353                                         payloadPtr->setFrameHeight(height);
354                                 }
355                                 if (!oscl_strncmp(temp, "decode_buf=", oscl_strlen("decode_buf=")))
356                                 {
357                                     temp += oscl_strlen("decode_buf=");
358                                     temp = skip_whitespace(temp, tmp_end_line);
359                                     if (temp > tmp_end_line)
360                                     {
361                                         PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad decode_buf field"));
362                                         return SDP_BAD_MEDIA_FMTP;
363                                     }
364                                     uint32 dec;
365                                     if (PV_atoi(temp, 'd', tmp_end_line - temp, dec) == true)
366                                         payloadPtr->setMaxBufferSize(dec);
367                                 }
368                                 if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1;
369                                 temp = skip_whitespace(temp, line_end_ptr);
370                                 if (temp >= line_end_ptr)
371                                 {
372                                     PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=fmtp line format"));
373                                     return SDP_BAD_MEDIA_FMTP;
374                                 }
375                             }
376                         }
377                     }
378                     StrPtrLen fmsize("a=framesize:");
379                     if (!oscl_strncmp(line_start_ptr, fmsize.c_str(), fmsize.length()))
380                     {
381                         uint32 width, height;
382                         const char *sptr = line_start_ptr + fmsize.length();
383                         const char *eptr = skip_to_whitespace(sptr, line_end_ptr);
384 
385 
386                         if (sptr > eptr)
387                         {
388                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=framesize line format"));
389                             return SDP_BAD_MEDIA_FRAMESIZE;
390                         }
391                         uint32 payloadNo;
392                         if (PV_atoi(sptr, 'd', (eptr - sptr), payloadNo))
393                         {
394                             int p;
395                             if (!((m4v_mediaInfo *)m4Video)->lookupPayloadNumber(payloadNo, p))
396                                 break;
397 
398                         }
399                         else
400                         {
401                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=framesize line format - Bad payload number"));
402                             return SDP_BAD_MEDIA_FRAMESIZE;
403                         }
404 
405                         M4vPayloadSpecificInfoType* payloadPtr2 =
406                             (M4vPayloadSpecificInfoType*)m4Video->getPayloadSpecificInfoTypePtr(payloadNo);
407                         if (payloadPtr2 == NULL)
408                         {
409                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=framesize line format - payload pointer not found for payload"));
410                             return SDP_PAYLOAD_MISMATCH;
411                         }
412 
413                         sptr = eptr;
414                         sptr = skip_whitespace(sptr , line_end_ptr);
415 
416                         for (; *eptr != '-' ; ++eptr);
417 
418                         if (!PV_atoi(sptr, 'd', eptr - sptr, width))
419                         {
420                             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - Bad a=framesize line format"));
421                             return SDP_BAD_MEDIA_FRAMESIZE;
422                         }
423 
424                         eptr = eptr + 1;
425                         sptr = eptr;
426                         if (sptr > line_end_ptr)
427                             return SDP_BAD_MEDIA_FRAMESIZE;
428                         eptr = skip_to_line_term(sptr, line_end_ptr);
429                         if (!PV_atoi(sptr, 'd', eptr - sptr, height))
430                             return SDP_BAD_MEDIA_FRAMESIZE;
431 
432                         if (framesize_found_in_fmtp)
433                         {
434                             if ((int)width != payloadPtr2->getFrameWidth() || (int)height != payloadPtr2->getFrameHeight())
435                             {
436                                 return SDP_BAD_MEDIA_FRAMESIZE;
437                             }
438 
439                         }
440                         else
441                         {
442                             payloadPtr2->setFrameWidth(width);
443                             payloadPtr2->setFrameHeight(height);
444                         }
445 
446                     }
447                 }
448                 break;
449                 default:
450                     break;
451             }
452             current_start = line_end_ptr;
453         }
454 
455         sessionDescription *session = sdp->getSessionInfo();
456 
457         const char *altGroupBW = session->getAltGroupBW();
458         int length = session->getAltGroupBWLength();
459 
460         if (length > 0)
461         {
462             status = setDependentMediaId(altGroupBW, length, m4Video, alt_id);
463             if (status != SDP_SUCCESS)
464                 return SDP_BAD_MEDIA_ALT_ID;
465         }
466 
467         const char *altGroupLANG = session->getAltGroupLANG();
468         length = session->getAltGroupLANGLength();
469 
470         if (length > 0)
471         {
472             status = setDependentMediaId(altGroupLANG, length, m4Video, alt_id);
473             if (status != SDP_SUCCESS)
474                 return SDP_BAD_MEDIA_ALT_ID;
475         }
476 
477         if (m4Video->getCFieldStatus()  || session->getCFieldStatus())
478         {
479             //if sample rate is zero override with defaults
480             Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadSpecificInfoVector =
481                 m4Video->getPayloadSpecificInfoVector();
482             for (int ii = 0; ii < (int)payloadSpecificInfoVector.size(); ii++)
483             {
484                 if (payloadSpecificInfoVector[ii]->getSampleRate() == 0)
485                 {
486                     payloadSpecificInfoVector[ii]->sampleRate =
487                         PVMF_SDP_DEFAULT_MPEG4_VIDEO_SAMPLE_RATE;
488                 }
489             }
490             return SDP_SUCCESS;
491         }
492         else
493         {
494             PVMF_SDP_PARSER_LOGERROR((0, "SDPM4VMediaInfoParser::parseMediaInfo - No C field present"));
495             return SDP_FAILURE_NO_C_FIELD;
496         }
497     }
498 
499 }
500 
501