blob: 6e1069cf11eefa232658c78c8bd3b12be908ba02 [file] [log] [blame]
/* ------------------------------------------------------------------
* 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;
}
}
}