| /* ------------------------------------------------------------------ |
| * 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 "rfc3640_media_info_parser.h" |
| #include "oscl_string_utils.h" |
| #include "oscl_string_containers.h" |
| #include "sdp_error.h" |
| |
| SDP_ERROR_CODE |
| SDPRFC3640MediaInfoParser::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 VOLLength = 0; |
| int fmtp_cnt = 0 ; |
| bool sizelength_found_in_fmtp = false; |
| bool indexlength_found_in_fmtp = false; |
| bool indexDeltaLength_found_in_fmtp = false; |
| SDPAllocDestructDealloc<uint8> SDP_alloc; |
| int strmType = 5; |
| OsclMemoryFragment modeMemFrag = {NULL, 0}; |
| int decLength = 0; |
| |
| |
| while (get_next_line(current_start, end, |
| line_start_ptr, line_end_ptr)) |
| { |
| 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=fmtp:", oscl_strlen("a=fmtp:"))) |
| { |
| char *tmp_start_line, *tmp_end_line; |
| fmtp_cnt++ ; |
| |
| tmp_start_line = (char *)line_start_ptr + oscl_strlen("a=fmtp:"); |
| tmp_start_line = (char *)skip_whitespace(tmp_start_line, line_end_ptr); |
| if (tmp_start_line >= line_end_ptr) |
| { |
| break; |
| } |
| tmp_end_line = (char *)skip_to_whitespace(tmp_start_line, line_end_ptr); |
| if (tmp_end_line < tmp_start_line) |
| { |
| break; |
| } |
| tmp_start_line = tmp_end_line + 1; |
| tmp_start_line = (char *)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 ((line_end_ptr - tmp_start_line - 1) == ii) |
| { |
| tmp_end_line++; |
| } |
| if (!oscl_strncmp(temp, "config=", oscl_strlen("config="))) |
| { |
| uint32 currentLength; |
| temp += oscl_strlen("config="); |
| temp = skip_whitespace(temp, line_end_ptr); |
| if (temp >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - no data in config= field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| currentLength = (int)(tmp_end_line - temp) / 2; |
| |
| if (decLength < (int) currentLength) |
| |
| decLength = currentLength; |
| } |
| |
| if (!oscl_CIstrncmp(temp, "streamtype=", oscl_strlen("streamtype="))) |
| { |
| temp += oscl_strlen("streamtype="); |
| temp = skip_whitespace(temp, line_end_ptr); |
| if (temp >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad StreamType field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 type; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), type) == false) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad StreamType field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| else |
| strmType = type; |
| } |
| if (!oscl_strncmp(temp, "mode=", oscl_strlen("mode="))) |
| { |
| temp += oscl_strlen("mode="); |
| temp = skip_whitespace(temp, line_end_ptr); |
| if (temp >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad mode field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| modeMemFrag.ptr = (void*)temp; |
| modeMemFrag.len = (tmp_end_line - temp); |
| } |
| |
| 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, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| |
| } |
| } |
| } |
| |
| |
| current_start = line_end_ptr + 1; |
| } |
| |
| if (fmtp_cnt == 0 && isSipSdp == false) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - No fmtp line found")); |
| return SDP_BAD_MEDIA_FORMAT; |
| } |
| |
| if (NULL == modeMemFrag.ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - No mode field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| |
| if (VOLLength < 0) |
| { |
| VOLLength = 0; |
| } |
| |
| bool altMedia = false; |
| if (!alt_id || (alt_def_id == true)) |
| altMedia = false; |
| else |
| altMedia = true; |
| |
| void *memory = sdp->alloc(sizeof(rfc3640_mediaInfo), altMedia); |
| if (NULL == memory) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - memory allocation failure")); |
| return SDP_NO_MEMORY; |
| } |
| else |
| { |
| rfc3640_mediaInfo *m3640media = OSCL_PLACEMENT_NEW(memory, rfc3640_mediaInfo()); |
| |
| m3640media->setMediaInfoID(sdp->getMediaObjectIndex()); |
| m3640media->setStreamType(strmType); |
| m3640media->setModeType(modeMemFrag); |
| |
| // Allocate memory to the payload specific objects |
| for (uint32 ii = 0; ii < payload_vec.size(); ii++) |
| { |
| void* mem = m3640media->alloc(sizeof(RFC3640PayloadSpecificInfoType)); |
| if (mem == NULL) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Memory allocation failure")); |
| return SDP_NO_MEMORY; |
| } |
| else |
| { |
| RFC3640PayloadSpecificInfoType* payload = OSCL_PLACEMENT_NEW(mem, RFC3640PayloadSpecificInfoType(payload_vec[ii])); |
| (void) payload; |
| } |
| } |
| |
| |
| if (alt_id && !alt_def_id) |
| { |
| sdp->copyFmDefMedia(m3640media); |
| //empty alternate & default track ID vectors. |
| m3640media->resetAlternateTrackId(); |
| m3640media->resetDependentTrackId(); |
| } |
| |
| SDP_ERROR_CODE status = baseMediaInfoParser(buff, m3640media, index, alt_id, alt_def_id, isSipSdp); |
| if (status != SDP_SUCCESS) |
| { |
| return status; |
| } |
| |
| current_start = buff; |
| |
| |
| while (get_next_line(current_start, end, |
| line_start_ptr, line_end_ptr)) |
| { |
| switch (*line_start_ptr) |
| { |
| case 'a': |
| { |
| 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=fmtp:", oscl_strlen("a=fmtp:"))) |
| { |
| const char *tmp_start_line, *tmp_end_line; |
| 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, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad payload number")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| else |
| { |
| int p; |
| if (!m3640media->lookupPayloadNumber(payloadNumber, p)) |
| { |
| fmtp_cnt--; |
| break; |
| } |
| } |
| |
| RFC3640PayloadSpecificInfoType* payloadPtr = |
| (RFC3640PayloadSpecificInfoType*)m3640media->getPayloadSpecificInfoTypePtr(payloadNumber); |
| if (payloadPtr == NULL) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - payload pointer not found for payload")); |
| return SDP_PAYLOAD_MISMATCH; |
| } |
| |
| PVMF_SDP_PARSER_LOGINFO((0, "SDPRFC3640MediaInfoParser::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_CIstrncmp(temp, "profile-level-id=", oscl_strlen("profile-level-id="))) |
| { |
| temp += oscl_strlen("profile-level-id="); |
| temp = skip_whitespace(temp, line_end_ptr); |
| if (temp > line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad profile-level-id field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 pl; |
| if (PV_atoi(temp, 'd', tmp_end_line - temp , pl) == true) |
| payloadPtr->setProfileLevelID(pl); |
| |
| } |
| if (!oscl_CIstrncmp(temp, "sizelength=", oscl_strlen("SizeLength="))) |
| { |
| temp += oscl_strlen("SizeLength="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| sizelength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad sizelength field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setSizeLength(length); |
| } |
| if (!oscl_CIstrncmp(temp, "indexlength=", oscl_strlen("IndexLength="))) |
| { |
| temp += oscl_strlen("IndexLength="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexlength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad indexlength field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setIndexLength(length); |
| } |
| if (!oscl_CIstrncmp(temp, "indexdeltalength=", oscl_strlen("IndexDeltaLength="))) |
| { |
| temp += oscl_strlen("IndexDeltaLength="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexDeltaLength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad indexDeltaLength field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setIndexDeltaLength(length); |
| } |
| if (!oscl_CIstrncmp(temp, "CTSDeltaLength=", oscl_strlen("CTSDeltaLength="))) |
| { |
| temp += oscl_strlen("CTSDeltaLength="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexDeltaLength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad CTSDeltaLength field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setCTSDeltaLength(length); |
| } |
| if (!oscl_CIstrncmp(temp, "DTSDeltaLength=", oscl_strlen("DTSDeltaLength="))) |
| { |
| temp += oscl_strlen("DTSDeltaLength="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexDeltaLength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad DTSDeltaLength field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setDTSDeltaLength(length); |
| } |
| if (!oscl_CIstrncmp(temp, "constantDuration=", oscl_strlen("ConstantDuration="))) |
| { |
| temp += oscl_strlen("ConstantDuration="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexDeltaLength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad constantDuration field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setConstantDuration(length); |
| } |
| if (!oscl_CIstrncmp(temp, "maxDisplacement=", oscl_strlen("MaxDisplacement="))) |
| { |
| temp += oscl_strlen("MaxDisplacement="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexDeltaLength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad maxDisplacement field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setMaxDisplacement(length); |
| } |
| if (!oscl_CIstrncmp(temp, "de-interleaveBufferSize=", oscl_strlen("de-interleaveBufferSize="))) |
| { |
| temp += oscl_strlen("de-interleaveBufferSize="); |
| temp = skip_whitespace(temp, tmp_end_line); |
| indexDeltaLength_found_in_fmtp = true; |
| if (temp > tmp_end_line) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad de-interleaveBufferSize= field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 length; |
| if (PV_atoi(temp, 'd', (tmp_end_line - temp), length) == true) |
| payloadPtr->setDeInterleaveBufferSize(length); |
| } |
| if (!oscl_strncmp(temp, "config=", oscl_strlen("config="))) |
| { |
| |
| uint8 *mptr = SDP_alloc.allocate(decLength); |
| OsclRefCounterSA< SDPAllocDestructDealloc<uint8> > *refcnt = new OsclRefCounterSA< SDPAllocDestructDealloc<uint8> >(mptr); |
| OsclSharedPtr<uint8> decInfo(mptr, refcnt); |
| |
| temp += oscl_strlen("config="); |
| temp = skip_whitespace(temp, line_end_ptr); |
| if (temp >= line_end_ptr) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for config= field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| decLength = (int)(tmp_end_line - temp) / 2; |
| int idx = 0; |
| for (idx = 0; idx < decLength; idx++) |
| { |
| uint32 val; |
| if (PV_atoi((temp + 2*idx), 'x', 2, val) == false) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for config= field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| |
| *(decInfo + idx) = (uint8) val; |
| } |
| |
| if (payloadPtr) |
| { |
| payloadPtr->setDecoderSpecificInfo(decInfo); |
| payloadPtr->setDecoderSpecificInfoSize(decLength); |
| } |
| else |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - a=fmtp field format is incorrect for payload")); |
| return SDP_PAYLOAD_MISMATCH; |
| } |
| } |
| 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, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad decode_buf field")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| uint32 dec; |
| if (PV_atoi(temp, 'd', tmp_end_line - temp, dec) == true) |
| payloadPtr->setMaxBufferSize(dec); |
| } |
| 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, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format")); |
| return SDP_BAD_MEDIA_FMTP; |
| } |
| } |
| } |
| } |
| |
| } |
| break; |
| default: |
| break; |
| } |
| current_start = line_end_ptr; |
| } |
| |
| if (!(indexDeltaLength_found_in_fmtp && sizelength_found_in_fmtp && indexlength_found_in_fmtp)) |
| { |
| PVMF_SDP_PARSER_LOGERROR((0, "SDPRFC3640MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Required info missing")); |
| return SDP_MISSING_MEDIA_DESCRIPTION; |
| |
| } |
| sessionDescription *session = sdp->getSessionInfo(); |
| |
| const char *altGroupBW = session->getAltGroupBW(); |
| int length = session->getAltGroupBWLength(); |
| |
| if (length > 0) |
| { |
| status = setDependentMediaId(altGroupBW, length, m3640media, 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, m3640media, alt_id); |
| if (status != SDP_SUCCESS) |
| return SDP_BAD_MEDIA_ALT_ID; |
| } |
| |
| return SDP_SUCCESS; |
| } |
| |
| } |
| |