| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #include "amr_media_info_parser.h" |
| #include "oscl_string_utils.h" |
| #include "oscl_string_containers.h" |
| |
| SDP_ERROR_CODE |
| SDPAMRMediaInfoParser::parseMediaInfo(const char *buff, |
| const int index, |
| SDPInfo *sdp, |
| payloadVector payload_vec, |
| bool isSipSdp, |
| int alt_id, |
| bool alt_def_id) |
| { |
| |
| const char *current_start = buff; //Pointer to the beginning of the media text |
| const char *end = buff + index; //Pointer to the end of the media text |
| const char *line_start_ptr, *line_end_ptr; |
| int modes[] = {1, 2, 4, 8, 16, 32, 64, 128}; |
| |
| int fmtp_cnt = 0; |
| |
| bool altMedia = false; |
| if (!alt_id || (alt_def_id == true)) |
| altMedia = false; |
| else |
| altMedia = true; |
| void *memory = NULL; |
| |
| memory = sdp->alloc(sizeof(amr_mediaInfo), altMedia); |
| |
| if (NULL == memory) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - No Memory allocated")); |
| return SDP_NO_MEMORY; |
| } |
| else |
| { |
| amr_mediaInfo *amrA = OSCL_PLACEMENT_NEW(memory, amr_mediaInfo()); |
| |
| amrA->setMediaInfoID(sdp->getMediaObjectIndex()); |
| |
| // Allocate memory to the payload specific objects |
| for (uint32 ii = 0; ii < payload_vec.size(); ii++) |
| { |
| void* mem = amrA->alloc(sizeof(AmrPayloadSpecificInfoType)); |
| if (mem == NULL) |
| { |
| return SDP_NO_MEMORY; |
| } |
| else |
| { |
| AmrPayloadSpecificInfoType* amrPayload = OSCL_PLACEMENT_NEW(mem, AmrPayloadSpecificInfoType(payload_vec[ii])); |
| (void) amrPayload; |
| } |
| } |
| |
| if (alt_id && !alt_def_id) |
| { |
| sdp->copyFmDefMedia(amrA); |
| //empty alternate & default track ID vectors. |
| amrA->resetAlternateTrackId(); |
| amrA->resetDependentTrackId(); |
| } |
| |
| SDP_ERROR_CODE status = baseMediaInfoParser(buff, amrA, index , alt_id, alt_def_id, isSipSdp); |
| |
| if (status != SDP_SUCCESS) |
| { |
| return status; |
| } |
| |
| while (get_next_line(current_start, end, |
| line_start_ptr, line_end_ptr)) |
| { |
| switch (*line_start_ptr) |
| { |
| case 'a': |
| { |
| const char *sptr; |
| if ((!oscl_strncmp(line_start_ptr, "a=alt:", oscl_strlen("a=alt:"))) && (alt_def_id == false)) |
| { |
| line_start_ptr += oscl_strlen("a=alt:"); |
| for (; *line_start_ptr != ':'; line_start_ptr++); |
| line_start_ptr = line_start_ptr + 1; |
| } |
| if (!oscl_strncmp(line_start_ptr, "a=lang:", oscl_strlen("a=lang:"))) |
| { |
| sptr = line_start_ptr + oscl_strlen("a=lang:"); |
| sptr = skip_whitespace(sptr, line_end_ptr); |
| if (sptr >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=lang field bad")); |
| return SDP_BAD_MEDIA_LANG_FIELD; |
| } |
| OsclMemoryFragment memFrag; |
| memFrag.ptr = (void*)sptr; |
| memFrag.len = (line_end_ptr - sptr); |
| |
| ((amr_mediaInfo*)amrA)->setLang(memFrag); |
| } |
| |
| if (!oscl_strncmp(line_start_ptr, "a=maxptime:", oscl_strlen("a=maxptime:"))) |
| { |
| sptr = line_start_ptr + oscl_strlen("a=maxptime:"); |
| sptr = skip_whitespace(sptr, line_end_ptr); |
| if (sptr >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=maxptime field bad")); |
| return SDP_BAD_MEDIA_MAXPTIME; |
| } |
| uint32 maxptime = 0; |
| if (PV_atoi(sptr, 'd', (line_end_ptr - sptr), maxptime) == true) |
| { |
| ((amr_mediaInfo*)amrA)->setMaximumPTime(maxptime); |
| } |
| } |
| if (!oscl_strncmp(line_start_ptr, "a=fmtp:", oscl_strlen("a=fmtp:"))) |
| { |
| const char *tmp_start_line, *tmp_end_line; |
| |
| fmtp_cnt++; |
| |
| tmp_start_line = line_start_ptr + oscl_strlen("a=fmtp:"); |
| tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr); |
| if (tmp_start_line >= line_end_ptr) |
| { |
| break; |
| } |
| tmp_end_line = skip_to_whitespace(tmp_start_line, line_end_ptr); |
| if (tmp_end_line < tmp_start_line) |
| { |
| break; |
| } |
| uint32 payloadNumber; |
| if (PV_atoi(tmp_start_line, 'd', (tmp_end_line - tmp_start_line), payloadNumber) == false) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field bad for payload number")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| else |
| { |
| int p; |
| if (!amrA->lookupPayloadNumber(payloadNumber, p)) |
| { |
| fmtp_cnt--; |
| break; |
| } |
| } |
| |
| // payloadNumber is present in the mediaInfo. get the payload |
| // Specific pointer corresponding to this payload |
| AmrPayloadSpecificInfoType* payloadPtr = |
| (AmrPayloadSpecificInfoType*)amrA->getPayloadSpecificInfoTypePtr(payloadNumber); |
| if (payloadPtr == NULL) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - unable to find payload ptr for payload number")); |
| return SDP_PAYLOAD_MISMATCH; |
| } |
| |
| PVMF_SDP_PARSER_LOGINFO((0, "SDPAmrMediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNumber)); |
| |
| tmp_start_line = tmp_end_line + 1; |
| tmp_start_line = skip_whitespace(tmp_start_line, line_end_ptr); |
| if (tmp_start_line >= line_end_ptr) |
| { |
| break; |
| } |
| int ii = 0; |
| const char *temp = tmp_start_line; |
| for (ii = 0; ii < (line_end_ptr - tmp_start_line); ii++) |
| { |
| if ((tmp_start_line[ii] == ';') || (ii == (line_end_ptr - tmp_start_line) - 1)) |
| { |
| tmp_end_line = tmp_start_line + ii; |
| if (ii == (line_end_ptr - tmp_start_line) - 1) |
| { |
| tmp_end_line += 1; |
| } |
| if (!oscl_strncmp(temp, "maxptime=", oscl_strlen("maxptime="))) |
| { |
| temp += oscl_strlen("maxptime="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| if (temp >= tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for maxptime=")); |
| return SDP_BAD_MEDIA_MAXPTIME; |
| } |
| uint32 maxPTime; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), maxPTime) == true) |
| payloadPtr->setMaximumPTime(maxPTime); |
| } |
| if (!oscl_strncmp(temp, "crc", oscl_strlen("crc"))) |
| { |
| if (!oscl_strncmp(temp, "crc=0", oscl_strlen("crc=0"))) |
| payloadPtr->setCRC(false); |
| else |
| payloadPtr->setCRC(true); |
| |
| } |
| if (!oscl_strncmp(temp, "robust-sorting", oscl_strlen("robust-sorting"))) |
| { |
| |
| |
| //We need to make sure that we do not read beyond valid memory |
| if ((line_end_ptr - temp) >= (int)oscl_strlen("robust-sorting=0")) |
| { |
| if (oscl_strncmp(temp, "robust-sorting=0", oscl_strlen("robust-sorting=0"))) |
| { |
| payloadPtr->setRobustSorting(true); |
| } |
| } |
| else |
| { |
| payloadPtr->setRobustSorting(false); |
| } |
| } |
| if (!oscl_strncmp(temp, "octet-align", oscl_strlen("octet-align"))) |
| { |
| |
| //We need to make sure that we do not read beyond valid memory |
| if ((line_end_ptr - temp) >= (int) oscl_strlen("octet-align=0")) |
| { |
| if (oscl_strncmp(temp, "octet-align=0", oscl_strlen("octet-align=0"))) |
| { |
| payloadPtr->setOctetAlign(true); |
| } |
| } |
| else |
| { |
| payloadPtr->setOctetAlign(false); |
| } |
| } |
| if (!oscl_strncmp(temp, "interleaving=", oscl_strlen("interleaving="))) |
| { |
| temp += oscl_strlen("interleaving="); |
| temp = (char *)skip_whitespace(temp, tmp_end_line); |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for interleaving=")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 interleave; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), interleave) == true) |
| payloadPtr->setInterLeaving(interleave); |
| } |
| if (!oscl_strncmp(temp, "decode_buf=", oscl_strlen("decode_buf="))) |
| { |
| temp += oscl_strlen("decode_buf="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for decode_buf=")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 dec; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), dec) == true) |
| payloadPtr->setMaxBufferSize(dec); |
| } |
| if (!oscl_strncmp(temp, "mode-change-period=", oscl_strlen("mode-change-period="))) |
| { |
| temp += oscl_strlen("mode-change-period="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for mode-change-period=")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 mcp; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), mcp) == true) |
| payloadPtr->setModeChangePeriod(mcp); |
| } |
| if (!oscl_strncmp(temp, "mode-change-neighbor", oscl_strlen("mode-change-neighbor"))) |
| { |
| //We need to make sure that we do not read beyond valid memory |
| if ((line_end_ptr - temp) >= (int)oscl_strlen("mode-change-neighbor=0")) |
| { |
| if (oscl_strncmp(temp, "mode-change-neighbor=0", oscl_strlen("mode-change-neighbor=0"))) |
| { |
| payloadPtr->setModeChangeNeighbor(true); |
| } |
| } |
| else |
| { |
| payloadPtr->setModeChangeNeighbor(false); |
| } |
| } |
| if (!oscl_strncmp(temp, "mode-change-neighbor=1", oscl_strlen("mode-change-neighbor=1"))) |
| { |
| payloadPtr->setModeChangeNeighbor(true); |
| } |
| if (!oscl_strncmp(temp, "mode-set=", oscl_strlen("mode-set="))) |
| { |
| temp += oscl_strlen("mode-set="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad for mode-set=")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| int idx = 0; |
| int cModeList = 0; |
| const char *begin = temp, *end; |
| for (idx = 0; idx < (tmp_end_line - temp); idx++) |
| { |
| if ((temp[idx] == ',') || ((tmp_end_line - temp) - 1 == idx)) |
| { |
| { |
| end = temp + idx; |
| } |
| if ((tmp_end_line - temp) - 1 == idx) |
| { |
| end++; |
| } |
| uint32 temp_idx; |
| if (PV_atoi(begin, 'd', (end - begin), temp_idx) == true) cModeList += modes[temp_idx]; |
| begin = end + 1; |
| } |
| } |
| payloadPtr->setCodecModeList(cModeList); |
| } |
| if (tmp_end_line != line_end_ptr) temp = tmp_end_line + 1; |
| temp = skip_whitespace(temp, line_end_ptr); |
| if (temp >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPAMRMediaInfoParser::parseMediaInfo - a=fmtp field format is bad")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| } |
| } |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| current_start = line_end_ptr; |
| } |
| sessionDescription *session = sdp->getSessionInfo(); |
| |
| if (fmtp_cnt != amrA->getMediaPayloadNumberCount() && isSipSdp == false) |
| return SDP_PAYLOAD_MISMATCH; |
| |
| const char *altGroupBW = session->getAltGroupBW(); |
| int length = session->getAltGroupBWLength(); |
| |
| if (length > 0) |
| { |
| status = setDependentMediaId(altGroupBW, length, amrA, alt_id); |
| if (status != SDP_SUCCESS) |
| return SDP_BAD_MEDIA_ALT_ID; |
| } |
| |
| const char *altGroupLANG = session->getAltGroupLANG(); |
| length = session->getAltGroupLANGLength(); |
| |
| if (length > 0) |
| { |
| status = setDependentMediaId(altGroupLANG, length, amrA, alt_id); |
| if (status != SDP_SUCCESS) |
| return SDP_BAD_MEDIA_ALT_ID; |
| } |
| |
| if (amrA->getCFieldStatus() || session->getCFieldStatus()) |
| { |
| //if sample rate is zero override with defaults |
| Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadSpecificInfoVector = |
| amrA->getPayloadSpecificInfoVector(); |
| for (int ii = 0; ii < (int)payloadSpecificInfoVector.size(); ii++) |
| { |
| if (payloadSpecificInfoVector[ii]->getSampleRate() == 0) |
| { |
| payloadSpecificInfoVector[ii]->sampleRate = |
| PVMF_SDP_DEFAULT_AMR_SAMPLE_RATE; |
| } |
| } |
| return SDP_SUCCESS; |
| } |
| else |
| { |
| return SDP_FAILURE_NO_C_FIELD; |
| } |
| } |
| } |