/* ------------------------------------------------------------------ * 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 "h263_media_info_parser.h" #include "oscl_string_utils.h" #include "oscl_string_containers.h" SDP_ERROR_CODE SDPH263MediaInfoParser::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; bool framesize_found_in_fmtp = false; bool framesize_found = false; int fmtp_cnt = 0; bool altMedia = false; if (!alt_id || (alt_def_id == true)) altMedia = false; else altMedia = true; void *memory = sdp->alloc(sizeof(h263_mediaInfo), altMedia); if (NULL == memory) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Memory allocation failure")); return SDP_NO_MEMORY; } else { h263_mediaInfo *h263V = OSCL_PLACEMENT_NEW(memory, h263_mediaInfo()); h263V->setMediaInfoID(sdp->getMediaObjectIndex()); // Allocate memory to the payload specific objects for (uint32 ii = 0; ii < payload_vec.size(); ii++) { void* mem = h263V->alloc(sizeof(H263PayloadSpecificInfoType)); if (mem == NULL) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Memory allocation failure")); return SDP_NO_MEMORY; } else { H263PayloadSpecificInfoType* h263Payload = OSCL_PLACEMENT_NEW(mem, H263PayloadSpecificInfoType(payload_vec[ii])); (void) h263Payload; } } if (alt_id && !alt_def_id) { sdp->copyFmDefMedia(h263V); //empty alternate & default track ID vectors. h263V->resetAlternateTrackId(); h263V->resetDependentTrackId(); } SDP_ERROR_CODE status = baseMediaInfoParser(buff, h263V, 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': { 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; 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, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad payload number")); return SDP_BAD_MEDIA_FMTP; } else { int p; if (!h263V->lookupPayloadNumber(payloadNumber, p)) { fmtp_cnt--; break; } } // payloadNumber is present in the mediaInfo. get the payload // Specific pointer corresponding to this payload H263PayloadSpecificInfoType* payloadPtr = (H263PayloadSpecificInfoType*)h263V->getPayloadSpecificInfoTypePtr(payloadNumber); if (payloadPtr == NULL) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Unable to find payload pointer for payload")); return SDP_PAYLOAD_MISMATCH; } PVMF_SDP_PARSER_LOGINFO((0, "SDPH263MediaInfoParser::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, "profile=", oscl_strlen("profile="))) { temp += oscl_strlen("profile="); temp = skip_whitespace(temp, tmp_end_line); if (temp > tmp_end_line) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad profile= field")); return SDP_BAD_MEDIA_FMTP; } uint32 cp; if (PV_atoi(temp, 'd', (tmp_end_line - temp), cp) == true) payloadPtr->setCodecProfile(cp); } if (!oscl_strncmp(temp, "level=", oscl_strlen("level="))) { temp += oscl_strlen("level="); temp = skip_whitespace(temp, tmp_end_line); if (temp > tmp_end_line) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad level= field")); return SDP_BAD_MEDIA_FMTP; } uint32 cl; if (PV_atoi(temp, 'd', (tmp_end_line - temp), cl) == true) payloadPtr->setCodecLevel(cl); } if (!oscl_strncmp(temp, "framesize=", oscl_strlen("framesize="))) { framesize_found_in_fmtp = true; temp += oscl_strlen("framesize="); temp = skip_whitespace(temp, tmp_end_line); if (temp > tmp_end_line) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad framesize= field")); return SDP_BAD_MEDIA_FMTP; } const char *end = NULL; int idx = 0; for (idx = 0; idx < (tmp_end_line - temp); idx++) { if (temp[idx] == '-') { end = temp + idx; } } if (end == NULL) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - frame width missing")); return SDP_MISSING_MEDIA_DESCRIPTION; } uint32 width; if (PV_atoi(temp, 'd', (end - temp), width) == true) { payloadPtr->setFrameWidth(width); } temp = end + 1; temp = skip_whitespace(temp, tmp_end_line); if (temp > tmp_end_line) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - frame height missing")); return SDP_BAD_MEDIA_FMTP; } uint32 height; if (PV_atoi(temp, 'd', (tmp_end_line - temp), height) == true) { payloadPtr->setFrameHeight(height); } } 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, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format - Bad decode_buf= field")); return SDP_BAD_MEDIA_FMTP; } uint32 decode_buf; if (PV_atoi(temp, 'd', (tmp_end_line - temp), decode_buf) == true) payloadPtr->setMaxBufferSize(decode_buf); } 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, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=fmtp line format")); return SDP_BAD_MEDIA_FMTP; } } } } // end a=fmtp StrPtrLen fmsize("a=framesize:"); if (!oscl_strncmp(line_start_ptr, fmsize.c_str(), fmsize.length())) { uint32 width, height; const char *sptr = line_start_ptr + fmsize.length(); const char *eptr = skip_to_whitespace(sptr, line_end_ptr); if (sptr > eptr) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize line format")); return SDP_BAD_MEDIA_FRAMESIZE; } uint32 payloadNo; if (PV_atoi(sptr, 'd', (eptr - sptr), payloadNo)) { int p; if (!h263V->lookupPayloadNumber(payloadNo, p)) break; } else { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize line format - bad payload number")); return SDP_BAD_MEDIA_FRAMESIZE; } framesize_found = true; // payloadNumber is present in the mediaInfo. get the payload // Specific pointer corresponding to this payload H263PayloadSpecificInfoType* payloadPtr2 = (H263PayloadSpecificInfoType*)h263V->getPayloadSpecificInfoTypePtr(payloadNo); if (payloadPtr2 == NULL) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize - unable to find payload pointer for the payload")); return SDP_PAYLOAD_MISMATCH; } PVMF_SDP_PARSER_LOGINFO((0, "SDPH263MediaInfoParser::parseMediaInfo - processing payload number : %d", payloadNo)); sptr = eptr; sptr = skip_whitespace(sptr , line_end_ptr); for (; *eptr != '-' ; ++eptr); if (!PV_atoi(sptr, 'd', eptr - sptr, width)) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize line format - bad width factor")); return SDP_BAD_MEDIA_FRAMESIZE ; } eptr = eptr + 1; sptr = eptr; if (sptr > line_end_ptr) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize line format")); return SDP_BAD_MEDIA_FRAMESIZE; } eptr = skip_to_whitespace(sptr, line_end_ptr); if (!PV_atoi(sptr, 'd', eptr - sptr, height)) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize line format - Bad height factor")); return SDP_BAD_MEDIA_FRAMESIZE; } if (framesize_found_in_fmtp) { if ((int)width != payloadPtr2->getFrameWidth() || (int)height != payloadPtr2->getFrameHeight()) { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - Bad a=framesize line format - frame width & height mis match")); return SDP_BAD_MEDIA_FRAMESIZE; } } else { payloadPtr2->setFrameWidth(width); payloadPtr2->setFrameHeight(height); } } } break; default: { } break; } current_start = line_end_ptr; } sessionDescription *session = sdp->getSessionInfo(); const char *altGroupBW = session->getAltGroupBW(); int length = session->getAltGroupBWLength(); if (length > 0) { status = setDependentMediaId(altGroupBW, length, h263V, 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, h263V, alt_id); if (status != SDP_SUCCESS) return SDP_BAD_MEDIA_ALT_ID; } if ((h263V->getCFieldStatus() || session->getCFieldStatus())) { //if sample rate is zero override with defaults Oscl_Vector<PayloadSpecificInfoTypeBase*, SDPParserAlloc> payloadSpecificInfoVector = h263V->getPayloadSpecificInfoVector(); for (int ii = 0; ii < (int)payloadSpecificInfoVector.size(); ii++) { if (payloadSpecificInfoVector[ii]->getSampleRate() == 0) { payloadSpecificInfoVector[ii]->sampleRate = PVMF_SDP_DEFAULT_H263_SAMPLE_RATE; } } return SDP_SUCCESS; } else { PVMF_SDP_PARSER_LOGERROR((0, "SDPH263MediaInfoParser::parseMediaInfo - no c field")); return SDP_FAILURE_NO_C_FIELD; } } }