PVMFStatus PVMFBufferDataSink::PutData(PVMFSharedMediaMsgPtr aMsg) { OSCL_UNUSED_ARG(aMsg); iNumPktsReceived++; PVMFSharedMediaDataPtr mediaData; convertToPVMFMediaData(mediaData, aMsg); iNumBytesReceived += (mediaData->getFilledSize()); if (mediaData->getErrorsFlag()) iNumPktErrorsReceived++; return PVMFSuccess; }
//////////////////////////////////////////////////////////////////////////////////// ////// pvHttpDownloadInput implementation //////////////////////////////////////////////////////////////////////////////////// bool pvHttpDownloadInput::getValidMediaData(INPUT_DATA_QUEUE &aDataInQueue, PVMFSharedMediaDataPtr &aMediaData, bool &isEOS) { isEOS = false; //aMediaData.Bind(iCurrentInputMediaData); do { // There should be at least one media msg in the queue if (aDataInQueue.empty()) return false; // Check if the next incoming media msg is an EOS or not // Introducing a boolean variable aEOSMsg is for simulating connection shutdown cases bool aEOSMsg = aDataInQueue[0]->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID; if (aEOSMsg) { isEOS = true; aDataInQueue.erase(aDataInQueue.begin()); return true; } convertToPVMFMediaData(iCurrentInputMediaData, aDataInQueue[0]); aDataInQueue.erase(aDataInQueue.begin()); } while (isValidInput() == false); aMediaData.Bind(iCurrentInputMediaData); return true; }
OSCL_EXPORT_REF void PvmfPortBaseImpl::LogMediaDataInfo(PVMFSharedMediaDataPtr aMediaData, const char* msg, int32 qsize) //log media data info, description, and associated q-depth. { OSCL_UNUSED_ARG(aMediaData); OSCL_UNUSED_ARG(msg); OSCL_UNUSED_ARG(qsize); if (!iDatapathLogger) return; LOGDATAPATH( (0, "PORT %s %s MediaData SeqNum %d, SId %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , aMediaData->getSeqNum() , aMediaData->getStreamID() , aMediaData->getTimestamp() , qsize )); }
void PVMFBufferDataSource::TimeoutOccurred(int32 timerID, int32 timeoutInfo) { OSCL_UNUSED_ARG(timerID); unsigned bytesToSend = timeoutInfo; if (bytesToSend <= 0) return; if (!IsConnected()) return; // Create new media data buffer OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl = iMediaDataAlloc->allocate(bytesToSend); PVMFSharedMediaDataPtr mediaData; int leavecode = 0; OSCL_TRY(leavecode, mediaData = PVMFMediaData::createMediaData(mediaDataImpl)); OSCL_FIRST_CATCH_ANY(leavecode, return); // Send FSI if available if (iFsi) { OsclSharedPtr<PVMFMediaDataImpl> fsiMediaDataImpl = iMediaDataAlloc->allocate(iFsiLen); PVMFSharedMediaDataPtr fsiMediaData; OSCL_TRY(leavecode, fsiMediaData = PVMFMediaData::createMediaData(fsiMediaDataImpl)); OSCL_FIRST_CATCH_ANY(leavecode, return); OsclRefCounterMemFrag fsi_frag; fsiMediaData->getMediaFragment(0, fsi_frag); oscl_memcpy((uint8*)fsi_frag.getMemFragPtr(), iFsi, iFsiLen); fsi_frag.getMemFrag().len = iFsiLen; mediaData->setFormatSpecificInfo(fsi_frag); OSCL_DEFAULT_FREE(iFsi); iFsi = NULL; iFsiLen = 0; } // Retrieve memory fragment to write to OsclRefCounterMemFrag refCtrMemFrag; mediaData->getMediaFragment(0, refCtrMemFrag); if (refCtrMemFrag.getCapacity() < bytesToSend) return; oscl_memset((uint8*)refCtrMemFrag.getMemFragPtr(), 7, bytesToSend); mediaDataImpl->setMediaFragFilledLen(0, bytesToSend); mediaData->setTimestamp(iTimestamp); iTimestamp += iSampleInterval; // Send frame to downstream node PVMFSharedMediaMsgPtr mediaMsg; convertToPVMFMediaMsg(mediaMsg, mediaData); QueueOutgoingMsg(mediaMsg); }
OSCL_EXPORT_REF void PvmfPortBaseImpl::LogMediaMsgInfo(PVMFSharedMediaMsgPtr aMediaMsg, const char* msg, int32 qsize) //log media msg info, description, and associated q-depth. { OSCL_UNUSED_ARG(msg); OSCL_UNUSED_ARG(qsize); if (!iDatapathLogger) return; switch (aMediaMsg->getFormatID()) { case PVMF_MEDIA_CMD_BOS_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "BOS" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , qsize )); } break; case PVMF_MEDIA_CMD_EOS_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "EOS" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , qsize )); } break; case PVMF_MEDIA_CMD_BOC_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "BOC" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , qsize )); } break; case PVMF_MEDIA_CMD_EOC_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "EOC" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , qsize )); } break; case PVMF_MEDIA_MSG_DATA_FORMAT_ID: { PVMFSharedMediaDataPtr mediaData; convertToPVMFMediaData(mediaData, aMediaMsg); LOGDATAPATH( (0, "PORT %s %s MediaData SeqNum %d, SId %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , mediaData->getSeqNum() , mediaData->getStreamID() , mediaData->getTimestamp() , qsize )); } break; default: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %d, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , aMediaMsg->getFormatID() , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , qsize )); } break; } }
void PvmfPortBaseImpl::LogMediaMsgInfo(PVMFSharedMediaMsgPtr aMediaMsg, const char* msg, PvmfPortBaseImplQueue&q) //log media msg info, description, and associated q-depth. { // to avoid compiler warnings when logger is not available OSCL_UNUSED_ARG(msg); OSCL_UNUSED_ARG(q); switch (aMediaMsg->getFormatID()) { case PVMF_MEDIA_CMD_BOS_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "BOS" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , q.iQ.size() , q.iCapacity )); } break; case PVMF_MEDIA_CMD_EOS_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "EOS" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , q.iQ.size() , q.iCapacity )); } break; case PVMF_MEDIA_CMD_BOC_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "BOC" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , q.iQ.size() , q.iCapacity )); } break; case PVMF_MEDIA_CMD_EOC_FORMAT_ID: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %s, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , "EOC" , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , q.iQ.size() , q.iCapacity )); } break; case PVMF_MEDIA_MSG_DATA_FORMAT_ID: { PVMFSharedMediaDataPtr mediaData; convertToPVMFMediaData(mediaData, aMediaMsg); LOGDATAPATH( (0, "PORT %s %s MediaData SeqNum %d, SId %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , mediaData->getSeqNum() , mediaData->getStreamID() , mediaData->getTimestamp() , q.iQ.size() , q.iCapacity )); } break; default: { LOGDATAPATH( (0, "PORT %s %s MediaCmd FmtId %d, SeqNum %d, SId %d, ClipID %d, TS %d, Q-depth %d/%d", iPortName.get_cstr() , msg , aMediaMsg->getFormatID() , aMediaMsg->getSeqNum() , aMediaMsg->getStreamID() , aMediaMsg->getClipID() , aMediaMsg->getTimestamp() , q.iQ.size() , q.iCapacity )); } break; } }
/* ======================================================================== */ uint8 PV_LATM_Parser::composeMultipleFrame(PVMFSharedMediaDataPtr& mediaDataIn) { uint32 tmp; uint8 * myData; uint32 i; OsclRefCounterMemFrag memFragIn; mediaDataIn->getMediaFragment(0, memFragIn); // pool made for output data OsclRefCounterMemFrag memFragOut; mediaDataOut->getMediaFragment(0, memFragOut); int32 pktsize = memFragIn.getMemFrag().len; // make sure we have enough memory to hold the data if (bytesRead + pktsize > currSize) { uint8 * tempPtr = (uint8*) oscl_calloc(bytesRead + pktsize, sizeof(uint8)); if (tempPtr == NULL) { // memory problem? return FRAME_ERROR; } currSize = bytesRead + pktsize; oscl_memcpy(tempPtr, multiFrameBuf, bytesRead); oscl_free(multiFrameBuf); multiFrameBuf = tempPtr; } oscl_memcpy(multiFrameBuf + bytesRead, memFragIn.getMemFrag().ptr, pktsize); bytesRead += pktsize; //newpkt->frame_size = bytesRead; // to update number of bytes copied memFragOut.getMemFrag().len = bytesRead; mediaDataOut->setMediaFragFilledLen(0, bytesRead); mediaDataOut->setSeqNum(mediaDataIn->getSeqNum()); mediaDataOut->setTimestamp(mediaDataIn->getTimestamp()); if (mediaDataIn->getMarkerInfo()) { // means this is the last packet for this audioMuxElement myData = multiFrameBuf; uint32 outPtrPos = 0; for (i = 0;i <= sMC->numSubFrames;i++) { framesize = 0; do { tmp = *(myData); framesize += tmp; } while (*(myData++) == 0xff); //int32 bUsed = (framesize/255)+1; // 0-254: 1, 255-511: 2 ... // do a check on the last one if (i == sMC->numSubFrames && !sMC->otherDataPresent) { if (framesize != bytesRead - (myData - multiFrameBuf)) { // to update number of bytes copied memFragOut.getMemFrag().len = 0; mediaDataOut->setMediaFragFilledLen(0, 0); return FRAME_INCOMPLETE; } } oscl_memcpy((uint8*)memFragOut.getMemFrag().ptr + outPtrPos, myData, framesize); myData += framesize; outPtrPos += framesize; } // to update number of bytes copied memFragOut.getMemFrag().len = outPtrPos; mediaDataOut->setMediaFragFilledLen(0, outPtrPos); bytesRead = 0; framesize = 0; compositenumframes = 0; } else { compositenumframes++; if (compositenumframes < MAX_NUM_COMPOSITE_FRAMES) { return FRAME_INCOMPLETE; } else { return FRAME_ERROR; } } return FRAME_COMPLETE; }
uint8 PV_LATM_Parser::composeSingleFrame(PVMFSharedMediaDataPtr& mediaDataIn) { int32 tmp = 0; //changed OsclRefCounterMemFrag memFragIn; mediaDataIn->getMediaFragment(0, memFragIn); // pool made for output data OsclRefCounterMemFrag memFragOut; mediaDataOut->getMediaFragment(0, memFragOut); //uint8 * myData = newpkt->data; uint8 * myData = (uint8*)memFragIn.getMemFrag().ptr; /* * Total Payload length, in bytes, includes * length of the AudioMuxElement() * AudioMuxElement() * Other data (for RF3016 not supported) */ int32 pktsize = memFragIn.getMemFrag().len; int32 m_bit = mediaDataIn->getMarkerInfo(); /* * All streams have same time framing (there is only one stream anyway) */ if (firstBlock) { /* * AudioMuxElement() fits in a single rtp packet or this is the first * block of an AudioMuxElement() spread accross more than one rtp packet */ int32 bUsed = 0; /* * PayLoadlenghtInfo( ) */ do { tmp = *(myData++); /* get payload lenght 8-bit in bytes */ framesize += tmp; bUsed++; } while (tmp == 0xff); /* 0xff is the escape sequence for values bigger than 255 */ /* * PayLoadMux( ) */ bytesRead = (pktsize - bUsed); // framesize must be equal to the bytesRead if mbit is 1 // or greater than bytesRead if mbit is 0 if ((m_bit && framesize != bytesRead && !sMC->otherDataPresent) || (!m_bit && framesize < bytesRead && !sMC->otherDataPresent)) { // to update number of bytes copied memFragOut.getMemFrag().len = 0; mediaDataOut->setMediaFragFilledLen(0, 0); bytesRead = 0; return FRAME_ERROR; } oscl_memcpy((uint8*)memFragOut.getMemFrag().ptr, myData, bytesRead); //ptr +1 changed if (sMC->otherDataPresent) { ; /* dont' care at this point, no MUX other than aac supported */ } } else { /* * We have an AudioMuxElement() spread accross more than one rtp packet */ if ((m_bit && framesize != pktsize + (bytesRead - 1) && !sMC->otherDataPresent) /* last block */ || (!m_bit && framesize < pktsize + (bytesRead - 1) && !sMC->otherDataPresent) /* intermediate block */) { // to update number of bytes copied memFragOut.getMemFrag().len = 0; mediaDataOut->setMediaFragFilledLen(0, 0); return FRAME_ERROR; } /* * Accumulate blocks until the full frame is complete */ oscl_memcpy((uint8*)memFragOut.getMemFrag().ptr + bytesRead, myData, pktsize); bytesRead += pktsize; } // to update number of bytes copied memFragOut.getMemFrag().len = bytesRead; mediaDataOut->setMediaFragFilledLen(0, bytesRead); mediaDataOut->setSeqNum(mediaDataIn->getSeqNum()); mediaDataOut->setTimestamp(mediaDataIn->getTimestamp()); firstBlock = false; /* we already processed the first block, so this should be false */ if (m_bit) /* check if it is a complete packet (m bit ==1) */ { firstBlock = true; /* if m-bit is "1", then the farme fits in a block or this was the last block of the frame, set for next call */ framesize = 0; frameNum = 0; bytesRead = 0; compositenumframes = 0; } else { /* * We have an AudioMuxElement() spread accross more than one rtp packet */ compositenumframes++; if (compositenumframes < MAX_NUM_COMPOSITE_FRAMES) { // this is not yet a finished packet return FRAME_INCOMPLETE; } else { return FRAME_ERROR; } } return FRAME_COMPLETE; }
OSCL_EXPORT_REF uint8 PV_LATM_Parser::compose(PVMFSharedMediaDataPtr& mediaDataIn) { uint8 retVal = 0; OsclRefCounterMemFrag memFragIn; mediaDataIn->getMediaFragment(0, memFragIn); // Don't need the ref to iMediaData so unbind it mediaDataOut.Unbind(); int errcode = 0; OsclSharedPtr<PVMFMediaDataImpl> mediaDataImpl; OSCL_TRY_NO_TLS(iOsclErrorTrapImp, errcode, mediaDataImpl = iMediaDataSimpleAlloc.allocate((uint32)memFragIn.getMemFrag().len)); OSCL_FIRST_CATCH_ANY(errcode, return FRAME_OUTPUTNOTAVAILABLE); errcode = 0; OSCL_TRY_NO_TLS(iOsclErrorTrapImp, errcode, mediaDataOut = PVMFMediaData::createMediaData(mediaDataImpl, &iMediaDataMemPool)); OSCL_FIRST_CATCH_ANY(errcode, return FRAME_OUTPUTNOTAVAILABLE); OsclRefCounterMemFrag memFragOut; mediaDataOut->getMediaFragment(0, memFragOut); /* * Latch for very first packet, sequence number is not established yet. */ int32 seqNum = mediaDataIn->getSeqNum(); if (!firstPacket) { if ((seqNum - last_sequence_num) > 1) /* detect any gap in sequence */ { // means we missed an RTP packet. dropFrames = true; } } else { firstPacket = false; } last_timestamp = mediaDataIn->getTimestamp(); last_sequence_num = seqNum; last_mbit = mediaDataIn->getMarkerInfo(); if (dropFrames) { if (mediaDataIn->getMarkerInfo()) { /* * try to recover packet as sequencing was broken, new packet could be valid * it is possible that the received packet contains a complete audioMuxElement() * so try to retrieve it. */ dropFrames = false; } else { /* * we are in the middle of a spread audioMuxElement(), or faulty rtp header * return error */ framesize = 0; frameNum = 0; bytesRead = 0; compositenumframes = 0; /* * Drop frame as we are not certain if it is a valid frame */ memFragOut.getMemFrag().len = 0; mediaDataOut->setMediaFragFilledLen(0, 0); firstBlock = true; // set for next call return FRAME_ERROR; } } if (sMC->numSubFrames > 0 || (sMC->cpresent == 1 && ((*(uint8*)(memFragIn.getMemFrag().ptr)) &(0x80)))) { // this is a less efficient version that must be used when you know an AudioMuxElement has // more than one subFrame -- I also added the case where the StreamMuxConfig is inline // The reason for this is that the StreamMuxConfig can be possibly large and there is no // way to know its size without parsing it. (the problem is it can straddle an RTP boundary) // it is less efficient because it composes the AudioMuxElement in a separate buffer (one // oscl_memcpy() per rtp packet) then parses it (one oscl_memcpy() per audio frame to the output // buffer (newpkt->outptr)) when it gets a whole AudioMuxElement. // The function below does a oscl_memcpy() directly into the output buffer // note, composeMultipleFrame will also work for the simple case in case there is another reason // to have to use it.. retVal = composeMultipleFrame(mediaDataIn); } else { // this is an efficient version that can be used when you know an AudioMuxElement has // only one subFrame retVal = composeSingleFrame(mediaDataIn); } // set this to drop frames in the future -- till we find another marker bit if (retVal == FRAME_ERROR) { dropFrames = true; framesize = 0; frameNum = 0; bytesRead = 0; compositenumframes = 0; //changed memFragOut.getMemFrag().len = 0; mediaDataOut->setMediaFragFilledLen(0, 0); firstBlock = true; // set for next call } return retVal; }
//////////////////////////////////////////////////////////////////////////////////// ////// HttpParsingBasicObject implementation //////////////////////////////////////////////////////////////////////////////////// int32 HttpParsingBasicObject::parseResponse(INPUT_DATA_QUEUE &aDataQueue) { PVMFSharedMediaDataPtr mediaData; int32 status = getNextMediaData(aDataQueue, mediaData); if (status != PARSE_SUCCESS) { if (status == PARSE_EOS_INPUT_DATA) { return validateEOSInput(status); } return status; // no input data or eos } OsclRefCounterMemFrag fragIn; mediaData->getMediaFragment(0, fragIn); HttpParsingBasicObjectAutoCleanup cleanup(this); while (status == PARSE_SUCCESS) { RefCountHTTPEntityUnit entityUnit; int32 parsingStatus = iParser->parse(fragIn, entityUnit); if (parsingStatus < 0) { PVMF_PROTOCOL_ENGINE_LOGERRINFODATAPATH((0, "HttpParsingBasicObject::parseResponse(), iParser->parse() retval=%d(iHttpHeaderParsed=%d)", parsingStatus, (int32)iHttpHeaderParsed)); } else { // save output data if there is iOutputQueue->clear(); uint32 size = saveOutputData(entityUnit, *iOutputQueue); if (size == 0xFFFFFFFF) return PARSE_GENERAL_ERROR; if (parsingStatus == HTTPParser::PARSE_HEADER_AVAILABLE) { iHttpHeaderParsed = true; iParser->getContentInfo(iContentInfo); extractServerVersionNum(); // update BandWidthEstimationInfo iBWEstInfo.update(mediaData, iHttpHeaderParsed); // do sanity check for HTTP header int32 sanityCheckStatus = iParser->doSanityCheckForResponseHeader(); if (sanityCheckStatus == HTTPParser::PARSE_TRANSFER_ENCODING_NOT_SUPPORTED) { parsingStatus = sanityCheckStatus; } else { // output data status = iObserver->OutputDataAvailable(iOutputQueue, true); if (status < 0) return status; } } else if (iHttpHeaderParsed && size > 0) { iTotalDLHttpBodySize += size; if (iLatestMediaDataTimestamp < mediaData->getTimestamp()) iLatestMediaDataTimestamp = mediaData->getTimestamp(); // update BandWidthEstimationInfo iBWEstInfo.update(mediaData, iHttpHeaderParsed); PVMF_PROTOCOL_ENGINE_LOGERRINFODATAPATH((0, "HttpParsingBasicObject::parseResponse() file size = %d, download size = %d, curr_size = %d, new download size = %d", iContentInfo.iContentLength, iTotalDLHttpBodySize, size, iBWEstInfo.iTotalSizePerRequest)); } } // check the condition of whether parsing the current input is done or not // may send out callback for end of message or end of input cases if ((status = checkParsingDone(parsingStatus)) != PARSE_SUCCESS) { if (status != PROCESS_WAIT_FOR_INCOMING_DATA) { PVMF_PROTOCOL_ENGINE_LOGERRINFODATAPATH((0, "HttpParsingBasicObject::parseResponse() status=checkParsingDone(parsingStatus)); parsingStatus = %d , status = %d", parsingStatus, status)); } return status; } } return PARSE_SUCCESS; }