| /* ------------------------------------------------------------------ |
| * 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. |
| * ------------------------------------------------------------------- |
| */ |
| #ifndef PVMF_JB_JITTERBUFFERMISC_H_INCLUDED |
| #include "pvmf_jb_jitterbuffermisc.h" |
| #endif |
| |
| #ifndef PVMF_SM_NODE_EVENTS_H_INCLUDED |
| #include "pvmf_sm_node_events.h" |
| #endif |
| |
| #ifndef PVMF_BASIC_ERRORINFOMESSAGE_H_INCLUDED |
| #include "pvmf_basic_errorinfomessage.h" |
| #endif |
| |
| OSCL_EXPORT_REF PVMFJitterBufferMisc* PVMFJitterBufferMisc::New(PVMFJitterBufferMiscObserver* aObserver, PVMFMediaClock& aClientPlaybackClock, Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>& aPortParamsQueue) |
| { |
| int32 err = OsclErrNone; |
| PVMFJitterBufferMisc* ptr = NULL; |
| OSCL_TRY(err, ptr = OSCL_NEW(PVMFJitterBufferMisc, (aObserver, aClientPlaybackClock, aPortParamsQueue)); |
| ptr->Construct()); |
| if (err != OsclErrNone) |
| { |
| ptr = NULL; |
| } |
| return ptr; |
| } |
| |
| void PVMFJitterBufferMisc::Construct() |
| { |
| ipJBEventsClockLogger = PVLogger::GetLoggerObject("jitterbuffernode.eventsclock"); |
| ipRTCPDataPathLoggerIn = PVLogger::GetLoggerObject("datapath.sourcenode.jitterbuffer.rtcp.in"); |
| ipClockLoggerSessionDuration = PVLogger::GetLoggerObject("clock.streaming_manager.sessionduration"); |
| ipClockLogger = PVLogger::GetLoggerObject("clock.jitterbuffernode"); |
| ipDataPathLoggerIn = PVLogger::GetLoggerObject("datapath.sourcenode.jitterbuffer.in"); |
| ipDataPathLoggerOut = PVLogger::GetLoggerObject("datapath.sourcenode.jitterbuffer.out"); |
| ipDataPathLoggerRTCP = PVLogger::GetLoggerObject("datapath.sourcenode.jitterbuffer.rtcp"); |
| ipLogger = PVLogger::GetLoggerObject("PVMFJitterBufferMisc"); |
| ipClockLoggerRebuff = PVLogger::GetLoggerObject("sourcenode.clock.rebuff"); |
| |
| CreateProtocolObjects(); |
| |
| ResetParams(false); |
| |
| //Look for the input ports in the port vect |
| //Look for the corresponding input port and the jitter buffer associated with it |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter_begin = irPortParamsQueue.begin(); |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter_end = irPortParamsQueue.end(); |
| while (iter_begin != iter_end) |
| { |
| PVMFJitterBufferPortParams* portParams = *iter_begin; |
| if (PVMF_JITTER_BUFFER_PORT_TYPE_INPUT == portParams->iTag)//input port |
| { |
| PVMFPortInterface* feedbackPort = NULL; |
| PVMFJitterBuffer* jitterBuffer = NULL; |
| PVRTCPChannelController* rtcpChannelController = NULL; |
| if (LookupRTCPChannelParams(&portParams->irPort, feedbackPort, jitterBuffer)) |
| { |
| rtcpChannelController = PVRTCPChannelController::New(ipRTCPProtoImplementator, *jitterBuffer, feedbackPort, irClientPlaybackClock, *ipWallClock); |
| ipRTCPProtoImplementator->AddPVRTCPChannelController(rtcpChannelController); |
| } |
| } |
| iter_begin++; |
| } |
| } |
| |
| bool PVMFJitterBufferMisc::CreateProtocolObjects() |
| { |
| uint32 start = 0; |
| bool overflowFlag = false; |
| |
| ipEstimatedServerClock = OSCL_NEW(PVMFMediaClock, ()); |
| ipEstimatedServerClock->SetClockTimebase(iEstimatedServerClockTimeBase); |
| if (ipEstimatedServerClock) |
| { |
| ipEstimatedServerClock->Stop(); |
| ipEstimatedServerClock->SetStartTime32(start, PVMF_MEDIA_CLOCK_MSEC, overflowFlag); |
| } |
| |
| ipWallClock = OSCL_NEW(PVMFMediaClock, ()); |
| ipWallClock->SetClockTimebase(iWallClockTimeBase); |
| if (ipWallClock) |
| { |
| ipWallClock->SetStartTime32(start, PVMF_MEDIA_CLOCK_MSEC, overflowFlag); |
| } |
| |
| ipNonDecreasingClock = OSCL_NEW(PVMFMediaClock, ()); |
| ipNonDecreasingClock->SetClockTimebase(iNonDecreasingTimeBase); |
| if (ipNonDecreasingClock) |
| { |
| ipNonDecreasingClock->SetStartTime32(start, PVMF_MEDIA_CLOCK_MSEC, overflowFlag); |
| } |
| |
| ipEventNotifier = PVMFJBEventNotifier::New(*ipNonDecreasingClock, irClientPlaybackClock, *ipEstimatedServerClock); |
| |
| return true; |
| } |
| |
| void PVMFJitterBufferMisc::ResetParams(bool aReleaseMemory) |
| { |
| if (ipFireWallPacketExchangerImpl && aReleaseMemory) |
| { |
| OSCL_DELETE(ipFireWallPacketExchangerImpl); |
| } |
| |
| ipFireWallPacketExchangerImpl = NULL; |
| |
| iSessionDuration = 0; |
| iStreamingSessionExpired = false; |
| iPlayDurationAvailable = false; |
| iBroadcastSession = false; |
| |
| iPlayStartTimeInMS = 0; |
| iPlayStopTimeInMS = 0; |
| iPlayStopTimeAvailable = false; |
| |
| |
| iFireWallPacketsExchangeEnabled = true; |
| iEstimatedServerClockUpdateCallbackId = 0; |
| iEstimatedServerClockUpdateCallbackPending = false; |
| |
| |
| } |
| |
| OSCL_EXPORT_REF PVMFJitterBufferMisc::~PVMFJitterBufferMisc() |
| { |
| ResetParams(true); |
| if (ipRTCPProtoImplementator) |
| { |
| ipRTCPProtoImplementator->RemoveAllRTCPChannelControllers(); |
| OSCL_DELETE(ipRTCPProtoImplementator); |
| } |
| |
| if (ipEventNotifier) |
| { |
| OSCL_DELETE(ipEventNotifier); |
| } |
| |
| if (ipSessionDurationTimer) |
| { |
| OSCL_DELETE(ipSessionDurationTimer); |
| } |
| |
| if (ipEstimatedServerClock) |
| { |
| OSCL_DELETE(ipEstimatedServerClock); |
| } |
| |
| if (ipWallClock) |
| { |
| OSCL_DELETE(ipWallClock); |
| } |
| |
| if (ipNonDecreasingClock) |
| { |
| OSCL_DELETE(ipNonDecreasingClock); |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::StreamingSessionStarted() |
| { |
| //if not already started... |
| if (ipNonDecreasingClock) |
| { |
| ipNonDecreasingClock->Start(); |
| } |
| |
| if (ipWallClock) |
| { |
| //Starts if not already running, check for state |
| ipWallClock->Start(); |
| } |
| |
| //Estimated server is to be updated only by the jitter buffer. |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParam = *iter; |
| if (pPortParam) |
| { |
| PVMFJitterBuffer* jitterBuffer = pPortParam->ipJitterBuffer; |
| if (jitterBuffer) |
| { |
| jitterBuffer->StreamingSessionStarted(); |
| } |
| } |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::StreamingSessionStopped() |
| { |
| Reset(); |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParam = *iter; |
| if (pPortParam) |
| { |
| PVMFJitterBuffer* jitterBuffer = pPortParam->ipJitterBuffer; |
| if (jitterBuffer) |
| { |
| jitterBuffer->StreamingSessionStopped(); |
| } |
| } |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::StreamingSessionPaused() |
| { |
| ipNonDecreasingClock->Pause(); |
| ipEstimatedServerClock->Pause(); |
| if (ipSessionDurationTimer) |
| ipSessionDurationTimer->Cancel(); |
| |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParam = *iter; |
| if (pPortParam) |
| { |
| PVMFJitterBuffer* jitterBuffer = pPortParam->ipJitterBuffer; |
| if (jitterBuffer) |
| { |
| jitterBuffer->StreamingSessionPaused(); |
| } |
| } |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::StreamingSessionBufferingStart() |
| { |
| if (ipSessionDurationTimer) |
| ipSessionDurationTimer->Cancel(); |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::StreamingSessionBufferingEnd() |
| { |
| if (ipSessionDurationTimer) |
| { |
| ComputeCurrentSessionDurationMonitoringInterval(); |
| ipSessionDurationTimer->Start(); |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::SetBroadcastSession() |
| { |
| iBroadcastSession = true; |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::ResetEstimatedServerClock() |
| { |
| if (ipEstimatedServerClock) |
| { |
| uint32 start = 0; |
| ipEstimatedServerClock->Stop(); |
| bool overflowFlag = false; |
| ipEstimatedServerClock->SetStartTime32(start, PVMF_MEDIA_CLOCK_MSEC, overflowFlag); |
| } |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::PrepareForRepositioning(bool oUseExpectedClientClockVal, uint32 aExpectedClientClockVal) |
| { |
| bool overflowFlag = false; |
| |
| //A session will have three things |
| //Media channel : Valid for any type of streaming |
| //Feedback Channel : Valid for RTSP based streaming |
| //Session Info : Valid for any type of streaming |
| |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator it; |
| for (it = irPortParamsQueue.begin(); |
| it != irPortParamsQueue.end(); |
| it++) |
| { |
| PVMFJitterBufferPortParams* pPortParam = *it; |
| if (pPortParam->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| pPortParam->ipJitterBuffer->PrepareForRepositioning(); |
| } |
| } |
| |
| PVMFTimestamp ts = 0; |
| if (oUseExpectedClientClockVal) |
| { |
| ts = aExpectedClientClockVal; |
| } |
| else |
| { |
| //reset player clock |
| ts = GetActualMediaDataTSAfterSeek(); |
| } |
| |
| irClientPlaybackClock.Stop(); |
| irClientPlaybackClock.SetStartTime32(ts, |
| PVMF_MEDIA_CLOCK_MSEC, overflowFlag); |
| |
| LOGCLIENTANDESTIMATEDSERVCLK_DATAPATH; |
| LOGCLIENTANDESTIMATEDSERVCLK_DATAPATH_OUT; |
| LOGCLIENTANDESTIMATEDSERVCLK_REBUFF; |
| |
| if (ipRTCPProtoImplementator) |
| ipRTCPProtoImplementator->Prepare(true); |
| iStreamingSessionExpired = false; |
| |
| return true; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::PurgeElementsWithNPTLessThan(NptTimeFormat &aNPTTime) |
| { |
| if (aNPTTime.npt_format != NptTimeFormat::NPT_SEC) |
| { |
| return false; |
| } |
| |
| uint32 i; |
| for (i = 0; i < irPortParamsQueue.size(); i++) |
| { |
| PVMFJitterBufferPortParams* portParams = irPortParamsQueue[i]; |
| portParams->irPort.ClearMsgQueues(); |
| } |
| |
| for (i = 0; i < irPortParamsQueue.size(); i++) |
| { |
| PVMFJitterBufferPortParams* portParams = irPortParamsQueue[i]; |
| if (portParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (portParams->ipJitterBuffer != NULL) |
| { |
| //portParams.iJitterBuffer->FlushJitterBuffer(); |
| PVMFTimestamp baseTS = 1000 * aNPTTime.npt_sec.sec + aNPTTime.npt_sec.milli_sec; |
| |
| portParams->iMediaClockConverter.set_clock_other_timescale(baseTS, 1000); |
| baseTS = portParams->iMediaClockConverter.get_current_timestamp(); |
| portParams->ipJitterBuffer->PurgeElementsWithTimestampLessThan(baseTS); |
| } |
| } |
| } |
| |
| // Update client clock here to avoid premature buffer fullness |
| PVMFTimestamp ts = 1000 * aNPTTime.npt_sec.sec + aNPTTime.npt_sec.milli_sec; |
| bool overflowFlag = false; |
| irClientPlaybackClock.Stop(); |
| irClientPlaybackClock.SetStartTime32(ts, PVMF_MEDIA_CLOCK_MSEC, overflowFlag); |
| return true; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::IsSessionExpired() |
| { |
| return iStreamingSessionExpired; |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::Prepare() |
| { |
| if (ipNonDecreasingClock) |
| { |
| ipNonDecreasingClock->Start(); |
| } |
| |
| if (ipWallClock) |
| { |
| //Starts if not already running, check for state |
| ipWallClock->Start(); |
| } |
| |
| if (UseSessionDurationTimerForEOS()) |
| { |
| ipSessionDurationTimer = OSCL_NEW(PvmfJBSessionDurationTimer, (this)); |
| if (ipSessionDurationTimer && ipEstimatedServerClock) |
| { |
| ipSessionDurationTimer->SetEstimatedServerClock(ipEstimatedServerClock); |
| } |
| } |
| if (RTCPProtocolImplementorRequired()) |
| { |
| ipRTCPProtoImplementator = PVRTCPProtoImplementor::New(irClientPlaybackClock, *ipWallClock, this, iBroadcastSession); |
| |
| //Set the rate adaptaton parmas if not already set |
| PVMFPortInterface* feedbackPort = NULL; |
| PVMFJitterBuffer* jitterBuffer = NULL; |
| Oscl_Vector<RateAdapatationInfo, OsclMemAllocator>::iterator iter; |
| for (iter = iRateAdaptationInfos.begin(); iter < iRateAdaptationInfos.end(); iter++) |
| { |
| RateAdapatationInfo rateAdaptationInfo = *iter; |
| feedbackPort = NULL; |
| jitterBuffer = NULL; |
| if (LookupRTCPChannelParams(rateAdaptationInfo.iPort, feedbackPort, jitterBuffer)) |
| { |
| PVRTCPChannelController* rtcpChannelController = ipRTCPProtoImplementator->GetRTCPChannelController(feedbackPort); |
| if (rtcpChannelController) |
| { |
| rtcpChannelController->SetRateAdaptation(rateAdaptationInfo.iRateAdapatationInfo.iRateAdaptation, rateAdaptationInfo.iRateAdapatationInfo.iRateAdaptationFeedBackFrequency, rateAdaptationInfo.iRateAdapatationInfo.iRateAdaptationFreeBufferSpaceInBytes); |
| |
| } |
| else |
| { |
| PVMFJitterBufferPort* rtpDataPort = OSCL_STATIC_CAST(PVMFJitterBufferPort*, rateAdaptationInfo.iPort); |
| jitterBuffer = rtpDataPort->GetPortParams()->ipJitterBuffer; |
| PVMFJitterBufferPortParams* rtpPortParams = rtpDataPort->GetPortParams(); |
| PVMFJitterBufferPortParams* feedbackPortParams = NULL; |
| LocateFeedBackPort(rtpPortParams, feedbackPortParams); |
| if (feedbackPortParams) |
| { |
| feedbackPort = &feedbackPortParams->irPort; |
| } |
| rtcpChannelController = PVRTCPChannelController::New(ipRTCPProtoImplementator, *jitterBuffer, feedbackPort, irClientPlaybackClock, *ipWallClock); |
| rtcpChannelController->SetRateAdaptation(rateAdaptationInfo.iRateAdapatationInfo.iRateAdaptation, rateAdaptationInfo.iRateAdapatationInfo.iRateAdaptationFeedBackFrequency, rateAdaptationInfo.iRateAdapatationInfo.iRateAdaptationFreeBufferSpaceInBytes); |
| ipRTCPProtoImplementator->AddPVRTCPChannelController(rtcpChannelController); |
| } |
| } |
| } |
| |
| Oscl_Vector<RTCPParams, OsclMemAllocator>::iterator rtcpParamIter; |
| for (rtcpParamIter = iRTCPParamsVect.begin(); rtcpParamIter < iRTCPParamsVect.end(); rtcpParamIter++) |
| { |
| RTCPParams rtcpParams = *rtcpParamIter; |
| ipRTCPProtoImplementator->SetPortRTCPParams(rtcpParams.iFeedbackPort, rtcpParams.iNumSenders, rtcpParams.iRR, rtcpParams.iRS); |
| } |
| |
| { |
| //Provide media clcok converter |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *iter; |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| |
| SetMediaClockConverter(&pPortParams->irPort, &pPortParams->iMediaClockConverter); |
| } |
| } |
| } |
| } |
| |
| iRateAdaptationInfos.clear(); |
| iRTCPParamsVect.clear(); |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::Reset() |
| { |
| if (ipEventNotifier) |
| { |
| ipEventNotifier->CancelAllPendingCallbacks(); |
| } |
| if (ipSessionDurationTimer) |
| { |
| ipSessionDurationTimer->Stop(); |
| } |
| if (ipRTCPProtoImplementator) |
| { |
| ipRTCPProtoImplementator->Reset(); |
| } |
| if (ipFireWallPacketExchangerImpl) |
| { |
| ipFireWallPacketExchangerImpl->CancelFirewallPacketExchange(); |
| } |
| if (ipEstimatedServerClock) |
| { |
| ipEstimatedServerClock->Stop(); |
| } |
| if (ipWallClock) |
| { |
| ipWallClock->Stop(); |
| } |
| if (ipNonDecreasingClock) |
| { |
| ipNonDecreasingClock->Stop(); |
| } |
| |
| iSessionDuration = 0; |
| iStreamingSessionExpired = true; |
| iPlayDurationAvailable = false; |
| iBroadcastSession = false; |
| iFireWallPacketsExchangeEnabled = true; |
| } |
| |
| OSCL_EXPORT_REF PVMFStatus PVMFJitterBufferMisc::PrepareMediaReceivingChannel() |
| { |
| if (ipFireWallPacketExchangerImpl && iFireWallPacketsExchangeEnabled) |
| { |
| ipFireWallPacketExchangerImpl->InitiateFirewallPacketExchange(); |
| return PVMFPending; |
| } |
| else |
| { |
| if (!iFireWallPacketsExchangeEnabled) |
| { |
| ipObserver->MediaReceivingChannelPrepared(true); |
| return PVMFSuccess; |
| } |
| return PVMFPending; //Wait for the SetServerInfo call |
| } |
| } |
| |
| OSCL_EXPORT_REF PVMFStatus PVMFJitterBufferMisc::CancelMediaReceivingChannelPreparation() |
| { |
| if (ipFireWallPacketExchangerImpl) |
| ipFireWallPacketExchangerImpl->CancelFirewallPacketExchange(); |
| return PVMFSuccess; |
| } |
| |
| bool PVMFJitterBufferMisc::FirewallPacketExchangerRequired() const |
| { |
| if (iFireWallPacketsExchangeEnabled) |
| { |
| char mimeRequiredForFirewallPacketExchange[] = "rtp"; |
| char mediaChannelMimeType[255] = {'0'}; |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end(); iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *iter; |
| if (pPortParams && (pPortParams->ipJitterBuffer)) |
| { |
| oscl_memset(mediaChannelMimeType, 0, sizeof(mediaChannelMimeType)); |
| const char* tmpMediaChannelMimeType = pPortParams->ipJitterBuffer->GetMimeType(); |
| const int32 mediaChannelMimeLen = oscl_strlen(tmpMediaChannelMimeType); |
| if (tmpMediaChannelMimeType) |
| { |
| for (int ii = 0; ii < mediaChannelMimeLen; ii++) |
| { |
| mediaChannelMimeType[ii] = oscl_tolower(tmpMediaChannelMimeType[ii]); |
| } |
| mediaChannelMimeType[mediaChannelMimeLen] = '\0'; |
| } |
| |
| if (oscl_strstr(mediaChannelMimeType, mimeRequiredForFirewallPacketExchange)) |
| { |
| return true; |
| } |
| } |
| } |
| } |
| return false; |
| } |
| |
| bool PVMFJitterBufferMisc::RTCPProtocolImplementorRequired() const |
| { |
| char mimeRequiredForRTCPSupport[] = "rtp"; |
| char mediaChannelMimeType[255] = {'0'}; |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end(); iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *iter; |
| if (pPortParams && (pPortParams->ipJitterBuffer)) |
| { |
| oscl_memset(mediaChannelMimeType, 0, sizeof(mediaChannelMimeType)); |
| const char* tmpMediaChannelMimeType = pPortParams->ipJitterBuffer->GetMimeType(); |
| const int32 mediaChannelMimeLen = oscl_strlen(tmpMediaChannelMimeType); |
| if (tmpMediaChannelMimeType) |
| { |
| for (int ii = 0; ii < mediaChannelMimeLen; ii++) |
| { |
| mediaChannelMimeType[ii] = oscl_tolower(tmpMediaChannelMimeType[ii]); |
| } |
| mediaChannelMimeType[mediaChannelMimeLen] = '\0'; |
| } |
| |
| if (oscl_strstr(mediaChannelMimeType, mimeRequiredForRTCPSupport)) |
| { |
| return true; |
| } |
| } |
| } |
| return false;//based on mime type |
| } |
| |
| OSCL_EXPORT_REF PVMFStatus PVMFJitterBufferMisc::ProcessFeedbackMessage(PVMFJitterBufferPortParams& aParam, PVMFSharedMediaMsgPtr aMsg) |
| { |
| PVMFStatus status = PVMFSuccess; |
| if (ipRTCPProtoImplementator) |
| { |
| status = ipRTCPProtoImplementator->ProcessRTCPReport(&aParam.irPort, aMsg); |
| } |
| else |
| { |
| status = PVMFFailure; |
| } |
| return status; |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::SetRateAdaptationInfo(PVMFPortInterface* aPort, bool aRateAdaptation, uint32 aRateAdaptationFeedBackFrequency, uint32 aRateAdaptationFreeBufferSpaceInBytes) |
| { |
| //Persist it: We'll update it when RTCP controller will be prepared |
| RateAdapatationInfo rateAdadpatatinInfo; |
| rateAdadpatatinInfo.iPort = aPort; |
| rateAdadpatatinInfo.iRateAdapatationInfo.iRateAdaptation = aRateAdaptation; |
| rateAdadpatatinInfo.iRateAdapatationInfo.iRateAdaptationFeedBackFrequency = aRateAdaptationFeedBackFrequency; |
| rateAdadpatatinInfo.iRateAdapatationInfo.iRateAdaptationFreeBufferSpaceInBytes = aRateAdaptationFreeBufferSpaceInBytes; |
| iRateAdaptationInfos.push_back(rateAdadpatatinInfo); |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::SetRTCPIntervalInMicroSecs(uint32 aRTCPInterval) |
| { |
| if (ipRTCPProtoImplementator) |
| ipRTCPProtoImplementator->SetRTCPIntervalInMicroSecs(aRTCPInterval); |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::SetPortRTCPParams(PVMFPortInterface* aPort, int aNumSenders, uint32 aRR, uint32 aRS) |
| { |
| bool retval = false; |
| if (ipRTCPProtoImplementator) |
| retval = ipRTCPProtoImplementator->SetPortRTCPParams(aPort, aNumSenders, aRR, aRS); |
| //retval eq to false implies rtcp controller doesnt exist as fo now for the port "aPort" |
| if (!retval) |
| { |
| RTCPParams rtcpParams; |
| rtcpParams.iFeedbackPort = aPort; |
| rtcpParams.iNumSenders = aNumSenders; |
| rtcpParams.iRR = aRR; |
| rtcpParams.iRS = aRS; |
| iRTCPParamsVect.push_back(rtcpParams); |
| retval = true; |
| } |
| return retval; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::ResetSession() |
| { |
| iStreamingSessionExpired = false; |
| if (ipSessionDurationTimer) |
| { |
| ipSessionDurationTimer->Cancel(); |
| ipSessionDurationTimer->Stop(); |
| } |
| return true; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::SetSessionDurationExpired() |
| { |
| iStreamingSessionExpired = true; |
| if (ipSessionDurationTimer) |
| { |
| ipSessionDurationTimer->Cancel(); |
| ipSessionDurationTimer->Stop(); |
| } |
| |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator it; |
| for (it = irPortParamsQueue.begin(); it != irPortParamsQueue.end(); it++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *it; |
| |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| pPortParams->ipJitterBuffer->SetEOS(true); |
| } |
| } |
| |
| |
| uint32 timebase32 = 0; |
| uint32 clientClock32 = 0; |
| bool overflowFlag = false; |
| irClientPlaybackClock.GetCurrentTime32(clientClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32); |
| timebase32 = 0; |
| uint32 estServClock32 = 0; |
| ipEstimatedServerClock->GetCurrentTime32(estServClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32); |
| |
| PVMF_JB_LOGDATATRAFFIC_OUT((0, "PVMFJitterBufferMisc::SetSessionDurationExpired- Estimated Server Clock [%d] Client Clock[%d]", estServClock32, clientClock32)); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferMisc::SetSessionDurationExpired- Estimated Server Clock [%d] Client Clock[%d]", estServClock32, clientClock32)); |
| |
| return true; |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::MediaReceivingChannelPreparationRequired(bool aRequired) |
| { |
| iFireWallPacketsExchangeEnabled = aRequired; |
| } |
| |
| OSCL_EXPORT_REF PVMFMediaClock& PVMFJitterBufferMisc::GetEstimatedServerClock() |
| { |
| return *ipEstimatedServerClock; |
| } |
| |
| OSCL_EXPORT_REF PVMFJBEventNotifier* PVMFJitterBufferMisc::GetEventNotifier() |
| { |
| return ipEventNotifier; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::SetPlayRange(int32 aStartTimeInMS, int32 aStopTimeInMS, bool aPlayAfterASeek, bool aStopTimeAvailable) |
| { |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParam = *iter; |
| if (pPortParam && (PVMF_JITTER_BUFFER_PORT_TYPE_INPUT == pPortParam->iTag)) |
| { |
| PVMFJitterBuffer* jitterBuffer = pPortParam->ipJitterBuffer; |
| if (jitterBuffer) |
| { |
| jitterBuffer->SetPlayRange(aStartTimeInMS, aPlayAfterASeek, aStopTimeAvailable, aStopTimeInMS); |
| } |
| } |
| } |
| |
| //Configure the RTCP timer stuff |
| if (ipRTCPProtoImplementator) |
| { |
| ipRTCPProtoImplementator->Prepare(aPlayAfterASeek); |
| ipRTCPProtoImplementator->StartRTCPMessageExchange(); |
| } |
| |
| iPlayStartTimeInMS = aStartTimeInMS; |
| iPlayStopTimeInMS = aStopTimeInMS; |
| iPlayStopTimeAvailable = aStopTimeAvailable; |
| |
| if (iPlayStopTimeAvailable == true) |
| { |
| /* Start Session Duration Timer only if stop duration is set */ |
| if ((ipSessionDurationTimer) && (!iStreamingSessionExpired || (aPlayAfterASeek))) |
| { |
| ipSessionDurationTimer->Stop(); |
| iStreamingSessionExpired = false; |
| ipSessionDurationTimer->setSessionDurationInMS(((iPlayStopTimeInMS - iPlayStartTimeInMS) + PVMF_EOS_TIMER_GAURD_BAND_IN_MS)); |
| ComputeCurrentSessionDurationMonitoringInterval(); |
| ipSessionDurationTimer->Start(); |
| } |
| } |
| |
| if (aPlayAfterASeek) |
| { |
| //Will eventually update the estimated server clock |
| //This call to "GetActualMediaDataTSAfterSeek" will normalize the ts's across the jitter buffers |
| //associated with the streaming session |
| GetActualMediaDataTSAfterSeek(); |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *iter; |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (pPortParams->ipJitterBuffer != NULL) |
| { |
| pPortParams->ipJitterBuffer->AdjustRTPTimeStamp(); |
| } |
| } |
| } |
| } |
| return true; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::SetPortSSRC(PVMFPortInterface* aPort, uint32 aSSRC) |
| { |
| //Update with the JB |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParam = *iter; |
| if (pPortParam && ((&pPortParam->irPort) == aPort)) |
| { |
| PVMFJitterBuffer* jitterBuffer = pPortParam->ipJitterBuffer; |
| if (jitterBuffer) |
| { |
| jitterBuffer->setSSRC(aSSRC); |
| } |
| break; |
| } |
| } |
| //update port's ssrc with the Firewall controller |
| RTPSessionInfoForFirewallExchange rtpSessioninfo(aPort, aSSRC); |
| iRTPExchangeInfosForFirewallExchange.push_back(rtpSessioninfo); |
| return true; |
| } |
| |
| OSCL_EXPORT_REF uint32 PVMFJitterBufferMisc::GetEstimatedServerClockValue() |
| { |
| uint32 serverClock32 = 0; |
| bool overflowFlag = false; |
| ipEstimatedServerClock->GetCurrentTime32(serverClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC); |
| return serverClock32; |
| } |
| |
| OSCL_EXPORT_REF bool PVMFJitterBufferMisc::PlayStopTimeAvailable() const |
| { |
| return iPlayStopTimeAvailable; |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::SetServerInfo(PVMFJitterBufferFireWallPacketInfo& aServerInfo) |
| { |
| if (iFireWallPacketsExchangeEnabled) |
| { |
| if (!ipFireWallPacketExchangerImpl) |
| { |
| //create it and start firewall packet exchange |
| ipFireWallPacketExchangerImpl = PVFirewallPacketExchangeImpl::New(aServerInfo, *ipEventNotifier, ipObserver); |
| Oscl_Vector<RTPSessionInfoForFirewallExchange, OsclMemAllocator>::iterator iter; |
| for (iter = iRTPExchangeInfosForFirewallExchange.begin(); iter != iRTPExchangeInfosForFirewallExchange.end(); iter++) |
| { |
| ipFireWallPacketExchangerImpl->SetRTPSessionInfoForFirewallExchange(*iter); |
| } |
| ipFireWallPacketExchangerImpl->InitiateFirewallPacketExchange(); |
| } |
| else |
| { |
| OSCL_ASSERT(false); |
| } |
| } |
| } |
| |
| OSCL_EXPORT_REF PVMFTimestamp PVMFJitterBufferMisc::GetMaxMediaDataTS() |
| { |
| PVMFTimestamp mediaTS = 0; |
| uint32 in_wrap_count = 0; |
| uint32 i; |
| |
| uint32 numOfJitterBuffers = 0; |
| for (i = 0; i < irPortParamsQueue.size(); i++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = irPortParamsQueue[i]; |
| |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (pPortParams->ipJitterBuffer != NULL) |
| { |
| PVMFTimestamp ts = |
| pPortParams->ipJitterBuffer->peekNextElementTimeStamp(); |
| ++numOfJitterBuffers; |
| /* |
| * Convert Time stamp to milliseconds |
| */ |
| pPortParams->iMediaClockConverter.set_clock(ts, in_wrap_count); |
| PVMFTimestamp converted_ts = |
| pPortParams->iMediaClockConverter.get_converted_ts(1000); |
| if (converted_ts > mediaTS) |
| { |
| mediaTS = converted_ts; |
| } |
| } |
| } |
| } |
| |
| if (numOfJitterBuffers > 1) //Need to normalize ts across jb's with the session (E.g. RTSP based streaming). |
| { |
| for (i = 0; i < irPortParamsQueue.size(); i++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = irPortParamsQueue[i]; |
| |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (pPortParams->ipJitterBuffer != NULL) |
| { |
| pPortParams->ipJitterBuffer->SetAdjustedTSInMS(mediaTS); |
| } |
| } |
| } |
| } |
| |
| return mediaTS; |
| } |
| |
| /* computes the max next ts of all tracks */ |
| OSCL_EXPORT_REF PVMFTimestamp PVMFJitterBufferMisc::GetActualMediaDataTSAfterSeek() |
| { |
| PVMFTimestamp mediaTS = 0; |
| uint32 in_wrap_count = 0; |
| uint32 i; |
| |
| uint32 numOfJitterBuffers = 0; |
| for (i = 0; i < irPortParamsQueue.size(); i++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = irPortParamsQueue[i]; |
| |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (pPortParams->ipJitterBuffer != NULL) |
| { |
| PVMFTimestamp ts = |
| pPortParams->ipJitterBuffer->peekNextElementTimeStamp(); |
| ++numOfJitterBuffers; |
| /* |
| * Convert Time stamp to milliseconds |
| */ |
| pPortParams->iMediaClockConverter.set_clock(ts, in_wrap_count); |
| PVMFTimestamp converted_ts = |
| pPortParams->iMediaClockConverter.get_converted_ts(1000); |
| if (converted_ts > mediaTS) |
| { |
| mediaTS = converted_ts; |
| } |
| } |
| } |
| } |
| |
| if (numOfJitterBuffers > 1) //Need to normalize ts across jb's with the session (E.g. RTSP based streaming). |
| { |
| for (i = 0; i < irPortParamsQueue.size(); i++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = irPortParamsQueue[i]; |
| |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (pPortParams->ipJitterBuffer != NULL) |
| { |
| pPortParams->ipJitterBuffer->SetAdjustedTSInMS(mediaTS); |
| } |
| } |
| } |
| } |
| |
| return mediaTS; |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::SetMediaClockConverter(PVMFPortInterface* apPort, MediaClockConverter* apMediaClockConverter) |
| { |
| PVMFPortInterface* feedbackPort = NULL; |
| PVMFJitterBuffer* jitterBuffer = NULL; |
| if (LookupRTCPChannelParams(apPort, feedbackPort, jitterBuffer)) |
| { |
| PVRTCPChannelController* rtcpChannelController = ipRTCPProtoImplementator->GetRTCPChannelController(feedbackPort); |
| if (rtcpChannelController) |
| { |
| rtcpChannelController->SetMediaClockConverter(apMediaClockConverter); |
| } |
| } |
| } |
| |
| OSCL_EXPORT_REF void PVMFJitterBufferMisc::ProcessFirstPacketAfterSeek() |
| { |
| //This call to "GetActualMediaDataTSAfterSeek" will normalize the ts's across the jitter buffers |
| //associated with the streaming session |
| GetActualMediaDataTSAfterSeek(); |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end() ; iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *iter; |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| if (pPortParams->ipJitterBuffer != NULL) |
| { |
| pPortParams->ipJitterBuffer->AdjustRTPTimeStamp(); |
| } |
| } |
| } |
| } |
| |
| PVMFStatus PVMFJitterBufferMisc::RTCPPacketReceived(RTCPPacketType aPacketType, PVRTCPChannelController* aController) |
| { |
| PVMF_JB_LOG_RTCPDATATRAFFIC_IN_E((0, "PVMFJitterBufferMisc::RTCPPacketReceived -- iPlayStopTimeAvailable[%d]", iPlayStopTimeAvailable)); |
| if (BYE_RTCP_PACKET == aPacketType && aController) |
| { |
| //for live streams, treat RTCP BYE as EOS |
| if (iPlayStopTimeAvailable == false) |
| { |
| PVMF_JB_LOGDATATRAFFIC_IN((0, "USING RTCP_BYE TO TRIGGER EOS: Mime=%s", aController->GetJitterBuffer().GetMimeType())); |
| PVMF_JB_LOGDATATRAFFIC_OUT((0, "USING RTCP_BYE TO TRIGGER EOS: Mime=%s", aController->GetJitterBuffer().GetMimeType())); |
| PVMF_JB_LOG_RTCPDATATRAFFIC_IN((0, "USING RTCP_BYE TO TRIGGER EOS: Mime=%s", aController->GetJitterBuffer().GetMimeType())); |
| SetSessionDurationExpired(); |
| ipEstimatedServerClock->Pause(); |
| ipWallClock->Pause(); |
| } |
| |
| if (ipRTCPProtoImplementator->RTCPByeReceivedOnAllControllers()) |
| { |
| SetSessionDurationExpired(); |
| ipEstimatedServerClock->Pause(); |
| ipWallClock->Pause(); |
| } |
| |
| PVUuid eventuuid = PVMFJitterBufferNodeEventTypeUUID; |
| int32 infocode = PVMFJitterBufferNodeRTCPBYERecvd; |
| |
| PVMFBasicErrorInfoMessage* eventmsg; |
| eventmsg = OSCL_NEW(PVMFBasicErrorInfoMessage, (infocode, eventuuid, NULL)); |
| PVMFErrorInfoMessageInterface* interimPtr = |
| OSCL_STATIC_CAST(PVMFErrorInfoMessageInterface*, eventmsg); |
| PVMFAsyncEvent asyncevent(PVMFInfoEvent, |
| PVMFInfoRemoteSourceNotification, |
| NULL, |
| OSCL_STATIC_CAST(PVInterface*, interimPtr), |
| (OsclAny*)(aController->GetJitterBuffer().GetMimeType()), |
| NULL, |
| 0); |
| ipObserver->ProcessRTCPControllerEvent(asyncevent); |
| eventmsg->removeRef(); |
| } |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVMFJitterBufferMisc::RTCPReportReadyToSend(PVMFPortInterface*& aPort, PVMFSharedMediaMsgPtr& aMessage) |
| { |
| ipObserver->MessageReadyToSend(aPort, aMessage); |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus PVMFJitterBufferMisc::ProcessInfoEvent(PVMFAsyncEvent& aEvent) |
| { |
| ipObserver->ProcessRTCPControllerEvent(aEvent); |
| return PVMFSuccess; |
| } |
| |
| void PVMFJitterBufferMisc::PVMFJBSessionDurationTimerEvent() |
| { |
| PVMF_JB_LOGCLOCK((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - Session Duration Timer Expired")); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - Session Duration Timer Expired")); |
| /* Check if the estimated server clock is past the expected value */ |
| uint32 expectedEstServClockVal = |
| ipSessionDurationTimer->GetExpectedEstimatedServClockValAtSessionEnd(); |
| uint32 timebase32 = 0; |
| uint32 estServClock = 0; |
| bool overflowFlag = false; |
| |
| |
| ipEstimatedServerClock->GetCurrentTime32(estServClock, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - CurrEstServClock = %2d", estServClock)); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - ExpectedEstServClock = %2d", expectedEstServClockVal)); |
| if (estServClock >= expectedEstServClockVal) |
| { |
| PVMF_JB_LOG_EVENTS_CLOCK((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent estServClock[%d] expectedEstServClockVal[%d]", estServClock, expectedEstServClockVal)); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - Session Duration Has Elapsed")); |
| iStreamingSessionExpired = true; |
| ipObserver->SessionSessionExpired(); |
| /* Cancel clock update notifications */ |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator it; |
| for (it = irPortParamsQueue.begin(); it != irPortParamsQueue.end(); it++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *it; |
| |
| if (pPortParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_INPUT) |
| { |
| pPortParams->ipJitterBuffer->SetEOS(true); |
| } |
| } |
| /* Pause Estimated server clock & RTCP Clock */ |
| ipEstimatedServerClock->Pause(); |
| ipWallClock->Pause(); |
| } |
| else |
| { |
| /* |
| * Since we monitor the session duration in intervals, it is possible that this call back |
| * happens when one such interval expires |
| */ |
| uint64 elapsedTime = ipSessionDurationTimer->GetMonitoringIntervalElapsed(); |
| uint32 elapsedTime32 = Oscl_Int64_Utils::get_uint64_lower32(elapsedTime); |
| ipSessionDurationTimer->UpdateElapsedSessionDuration(elapsedTime32); |
| uint32 totalSessionDuration = ipSessionDurationTimer->getSessionDurationInMS(); |
| uint32 elapsedSessionDurationInMS = ipSessionDurationTimer->GetElapsedSessionDurationInMS(); |
| if (elapsedSessionDurationInMS < totalSessionDuration) |
| { |
| uint32 interval = (totalSessionDuration - elapsedSessionDurationInMS); |
| if (interval > PVMF_JITTER_BUFFER_NODE_SESSION_DURATION_MONITORING_INTERVAL_MAX_IN_MS) |
| { |
| interval = PVMF_JITTER_BUFFER_NODE_SESSION_DURATION_MONITORING_INTERVAL_MAX_IN_MS; |
| } |
| ipSessionDurationTimer->setCurrentMonitoringIntervalInMS(interval); |
| ipSessionDurationTimer->ResetEstimatedServClockValAtLastCancel(); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - TotalDuration=%d, ElapsedDuration=%d, CurrMonitoringInterval=%d", totalSessionDuration, elapsedSessionDurationInMS, interval)); |
| } |
| else |
| { |
| /* |
| * 1) Register for est serv clock update notifications on all jitter buffers |
| * 2) Reschedule the session duration timer |
| */ |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - Past Session End Time - Starting to monitor Estimated Server Clock expectedEstServClockVal%d estServClock %d", expectedEstServClockVal, estServClock)); |
| |
| uint64 diff = (expectedEstServClockVal - estServClock); |
| uint32 diff32 = Oscl_Int64_Utils::get_uint64_lower32(diff); |
| |
| PVMFJBEventNotificationRequestInfo requestInfo(CLOCK_NOTIFICATION_INTF_TYPE_ESTIMATEDSERVER, this, NULL); |
| |
| if (iEstimatedServerClockUpdateCallbackPending) |
| { |
| ipEventNotifier->CancelCallBack(requestInfo, iEstimatedServerClockUpdateCallbackId); |
| iEstimatedServerClockUpdateCallbackPending = false; |
| } |
| |
| ipEventNotifier->RequestAbsoluteTimeCallBack(requestInfo, expectedEstServClockVal, iEstimatedServerClockUpdateCallbackId); |
| iEstimatedServerClockUpdateCallbackPending = true; |
| |
| /* |
| * This is intentional. We do not expect the session duration and monitoring |
| * intervals to exceed the max timer limit of 32 mins |
| */ |
| ipSessionDurationTimer->setSessionDurationInMS(diff32); |
| ipSessionDurationTimer->setCurrentMonitoringIntervalInMS(diff32); |
| ipSessionDurationTimer->ResetEstimatedServClockValAtLastCancel(); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - ExpectedEstServClock=%d EstServClock=%d", Oscl_Int64_Utils::get_uint64_lower32(expectedEstServClockVal), Oscl_Int64_Utils::get_uint64_lower32(estServClock))); |
| PVMF_JB_LOGCLOCK_SESSION_DURATION((0, "PVMFJitterBufferNode::PVMFJBSessionDurationTimerEvent - TotalDuration=%d, Interval=%d", diff32, diff32)); |
| } |
| ipSessionDurationTimer->Start(); |
| } |
| return; |
| } |
| |
| void PVMFJitterBufferMisc::ProcessCallback(CLOCK_NOTIFICATION_INTF_TYPE aClockNotificationInterfaceType, uint32 aCallBkId, const OsclAny* aContext, PVMFStatus aStatus) |
| { |
| OSCL_UNUSED_ARG(aClockNotificationInterfaceType); |
| OSCL_UNUSED_ARG(aContext); |
| if (aCallBkId == iEstimatedServerClockUpdateCallbackId && (PVMFSuccess == aStatus)) |
| { |
| ipSessionDurationTimer->EstimatedServerClockUpdated(); |
| } |
| } |
| |
| bool PVMFJitterBufferMisc::UseSessionDurationTimerForEOS() |
| { |
| char mimeForSessioDurationTmrNecessity[] = "rtp"; |
| char mediaChannelMimeType[255] = {'0'}; |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator iter; |
| for (iter = irPortParamsQueue.begin(); iter != irPortParamsQueue.end(); iter++) |
| { |
| PVMFJitterBufferPortParams* pPortParams = *iter; |
| if (pPortParams && (pPortParams->ipJitterBuffer)) |
| { |
| oscl_memset(mediaChannelMimeType, 0, sizeof(mediaChannelMimeType)); |
| const char* tmpMediaChannelMimeType = pPortParams->ipJitterBuffer->GetMimeType(); |
| const int32 mediaChannelMimeLen = oscl_strlen(tmpMediaChannelMimeType); |
| if (tmpMediaChannelMimeType) |
| { |
| for (int ii = 0; ii < mediaChannelMimeLen; ii++) |
| { |
| mediaChannelMimeType[ii] = oscl_tolower(tmpMediaChannelMimeType[ii]); |
| } |
| mediaChannelMimeType[mediaChannelMimeLen] = '\0'; |
| } |
| |
| if (oscl_strstr(mediaChannelMimeType, mimeForSessioDurationTmrNecessity)) |
| { |
| return true; |
| } |
| } |
| } |
| return false;//based on mime type |
| } |
| |
| void PVMFJitterBufferMisc::LogClientAndEstimatedServerClock(PVLogger* aLogger) |
| { |
| uint32 timebase32 = 0; |
| uint32 clientClock32 = 0; |
| uint32 serverClock32 = 0; |
| bool overflowFlag = false; |
| irClientPlaybackClock.GetCurrentTime32(clientClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32); |
| |
| if (ipEstimatedServerClock) |
| ipEstimatedServerClock->GetCurrentTime32(serverClock32, overflowFlag, PVMF_MEDIA_CLOCK_MSEC, timebase32); |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, aLogger, PVLOGMSG_INFO, (0, "Value of Client Clock %d and value of Estimated Sever Clock %d", clientClock32, serverClock32)); |
| } |
| |
| bool PVMFJitterBufferMisc::LookupRTCPChannelParams(PVMFPortInterface* rtpPort, PVMFPortInterface*& rtcpPort, PVMFJitterBuffer*& rtpPktJitterBuffer) |
| { |
| bool retval = false; |
| PVMFJitterBufferPort* jbInputPort = OSCL_STATIC_CAST(PVMFJitterBufferPort*, rtpPort); |
| PVMFJitterBufferPortParams* inputPortParams = jbInputPort->GetPortParams(); |
| PVMFJitterBufferPortParams* feedbackPortParams = NULL; |
| |
| if (LocateFeedBackPort(inputPortParams, feedbackPortParams)) |
| { |
| rtcpPort = &feedbackPortParams->irPort; |
| rtpPktJitterBuffer = inputPortParams->ipJitterBuffer; |
| retval = true; |
| } |
| return retval; |
| } |
| |
| bool PVMFJitterBufferMisc::LocateFeedBackPort(PVMFJitterBufferPortParams*& aInputPortParamsPtr, PVMFJitterBufferPortParams*& aFeedBackPortParamsPtr) |
| { |
| uint32 inputPortId = aInputPortParamsPtr->iId; |
| |
| /* Feedback port id must be inputPortId + 2 */ |
| |
| Oscl_Vector<PVMFJitterBufferPortParams*, OsclMemAllocator>::iterator it; |
| |
| for (it = irPortParamsQueue.begin(); it != irPortParamsQueue.end(); it++) |
| { |
| PVMFJitterBufferPortParams* portParams = *it; |
| if ((portParams->iTag == PVMF_JITTER_BUFFER_PORT_TYPE_FEEDBACK) && |
| ((int32)portParams->iId == (int32)inputPortId + 2)) |
| { |
| aFeedBackPortParamsPtr = portParams; |
| return true; |
| } |
| } |
| return false; |
| } |