blob: 788469e5a97d7f24283a47b23e5bae936a63dd9a [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 "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;
}
}