| /* ------------------------------------------------------------------ |
| * 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. |
| * ------------------------------------------------------------------- |
| */ |
| // ---------------------------------------------------------------------- |
| // |
| // This Software is an original work of authorship of PacketVideo Corporation. |
| // Portions of the Software were developed in collaboration with NTT DoCoMo, |
| // Inc. or were derived from the public domain or materials licensed from |
| // third parties. Title and ownership, including all intellectual property |
| // rights in and to the Software shall remain with PacketVideo Corporation |
| // and NTT DoCoMo, Inc. |
| // |
| // ----------------------------------------------------------------------- |
| /*****************************************************************************/ |
| /* file name : tsc_ce.c */ |
| /* file contents : Terminal State Control routine */ |
| /* draw : '96.10.04 */ |
| /*---------------------------------------------------------------------------*/ |
| /* amendment */ |
| /* Copyright (C) 1996 NTT DoCoMo */ |
| /*****************************************************************************/ |
| #include "tscmain.h" |
| #include "tsc_sub.h" /* Sub Routine Information Header */ |
| #include "tsc_constants.h" |
| #include "tsc_statemanager.h" |
| #include "tsc_capability.h" |
| #include "tsc_component.h" |
| |
| #define PV2WAY_DEFAULT_USER_INPUT_CAPABILITY_INDEX 2 /* Index for IA5 string */ |
| |
| ////////////////////////////////////////////////////////////////////////// |
| // Start the CE process by sending this terminals capabilites to the peer terminal |
| ////////////////////////////////////////////////////////////////////////// |
| void TSC_324m::CEStart(void) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "TSC_324m: CEStart\n")); |
| if (iCeRetries <= 0) |
| { |
| return; |
| } |
| if (iTSCcomponent->CEStart()) |
| { |
| iCeRetries--; |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| // CE User - Transfer.Indication primitive received from H.245 |
| //////////////////////////////////////////////////////////////////////// |
| void TSC_324m::CETransferIndication(OsclSharedPtr<S_TerminalCapabilitySet> tcs) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: CE transfer indication received.\n")); |
| |
| // Cancel timers for TCS receive |
| iTimer->Cancel(PV_TSC_TCS_RECEIVE_TIMER_ID); |
| iH223->EnableStuffing(false); |
| |
| Tsc324mNodeCommand* cmd = iTSCcomponent->GetCommand(); |
| if (cmd) |
| { |
| iCmdQueue.AddL(*cmd); |
| RunIfNotReady(); |
| } |
| |
| |
| //////////////////////// |
| // State = Call Setup |
| //////////////////////// |
| if (iTerminalStatus == PhaseD_CSUP) |
| { |
| // TRANSFER.response(CE) Primitive Send |
| if (Ce) Ce->TransferResponse(); |
| |
| ExtractTcsParameters(tcs); |
| |
| iTSCcomponent->CETransferIndication(tcs, iTerminalStatus); |
| |
| if (iTSCcomponent->GetVideoLayer() == 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::CETransferIndication - Failed to negotiate video layer.\n")); |
| iCeRetries = iN100; |
| iConnectFailReason = EPVT_FailedToNegotiate; |
| SessionClose_CSUP(); |
| } |
| if (iTSCstatemanager.ReadState(TSC_CE_RECEIVE) != COMPLETE) |
| { |
| iTSCstatemanager.WriteState(TSC_CE_RECEIVE, COMPLETE); |
| |
| if ((iTSCstatemanager.ReadState(TSC_MSD) == COMPLETE)) |
| { |
| int leave_status = 0; |
| OSCL_TRY(leave_status, TcsMsdComplete()); |
| OSCL_FIRST_CATCH_ANY(leave_status, void()); |
| if (leave_status != 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, |
| (0, "TSC_324m::CETransferIndication - Memory Allocation Failed.")); |
| SignalCsupComplete(PVMFErrNoMemory); |
| return; |
| } |
| } |
| } |
| } |
| ////////////////////////////////// |
| // State = Ongoing Communication |
| ////////////////////////////////// |
| else if (iTerminalStatus == PhaseE_Comm) |
| { |
| iTSCcomponent->CETransferIndication(tcs, iTerminalStatus); |
| if (Ce) Ce->TransferResponse(); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::CETransferIndication Error - invalid state(%d)", iTerminalStatus)); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| // CE User - Transfer.Confirm primitive received from H.245 |
| //////////////////////////////////////////////////////////////////////// |
| void TSC_324m::CETransferConfirm() |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::CETransferConfirm Capability Exchange Send...Complete.")); |
| //////////////////////// |
| // State = Call Setup |
| //////////////////////// |
| if (iTerminalStatus == PhaseD_CSUP || iTerminalStatus == PhaseE_Comm) |
| { |
| iTSCstatemanager.WriteState(TSC_CE_SEND, COMPLETE); |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::CETransferConfirm Error - Invalid state(%d)", iTerminalStatus)); |
| } |
| iCeRetries = iN100; /* Num CE retries left */ |
| } |
| |
| //////////////////////////////////////////////////////////////////////// |
| // CE User - Reject.Indication primitive received from H.245 |
| //////////////////////////////////////////////////////////////////////// |
| void TSC_324m::CERejectIndication(CESource source, CECause cause, CEDirection direction) |
| { |
| OSCL_UNUSED_ARG(cause); |
| |
| /* WWUAPI: four scenarios can cause this function being called |
| 1. INCOMING SE gets TCS again while in AWAITING RESPONSE state |
| We send out CE RPS as soon as we receive a TCS. It means the other temrinal |
| is a whacky terminal sending out successive TCS's. Maybe we just use the most |
| recent TCS ? |
| 2. OUTGOING SE gets REJECT while in AWAITING RESPONSE state |
| End Session and reset. |
| 3. TIMEOUT for OUTGOING SE |
| End Session and reset if we are in PhaseD_CSUP |
| 4. INCOMING SE gets RELEASE while in AWAITING RESPONSE |
| We took too much time to send a response and remote SE timed out. |
| End Session and reset |
| We need a fat brain in the future to handle all these unusual cases. |
| Here we just do nothing. |
| */ |
| |
| //////////////////////// |
| // State = Call Setup |
| //////////////////////// |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: CE Reject Indication received.")); |
| |
| if (iTerminalStatus == PhaseD_CSUP || iTerminalStatus == PhaseE_Comm) |
| { |
| if (direction == CE_OUTGOING) |
| { |
| if (source == CE_USER) /* Reject */ |
| { |
| iCeRetries = iN100; |
| iConnectFailReason = EPVT_ErrorRemoteRejected; |
| SessionClose_CSUP(); |
| } |
| else /* Caused by PROTOCOL, most likely due to timeouts */ |
| { |
| if (iCeRetries) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Starting CE Send.\n")); |
| CEStart(); /* INITIATE CE-SEND */ |
| } |
| else /* Retried enough. Call setup failed */ |
| { |
| iCeRetries = iN100; |
| iConnectFailReason = EPVT_Timeout; |
| SessionClose_CSUP(); |
| } |
| } |
| } |
| else /* INCOMING */ |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Capability Exchange(I)...Release received.\n")); |
| SessionClose_CSUP(); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::CERejectIndication Error - Invalid state(%d)", iTerminalStatus)); |
| } |
| } |
| |
| //////////////////////////////////////////////////////////////////////////// |
| // ExtractTcsParameters() (RAN-32K) |
| // |
| // This routine takes the incoming TerminalCapabilitySet |
| // and extracts the following useful parameters: |
| // {h263_qcifMPI, h263_maxBitRate, mpeg4_maxBitRate} |
| // The parameters are stored in globals and may be sent |
| // later to the application. |
| //////////////////////////////////////////////////////////////////////////// |
| void TSC_324m::ExtractTcsParameters(PS_TerminalCapabilitySet pTcs) |
| { |
| uint32 i; |
| PS_CapabilityTableEntry pCapEntry = NULL; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::ExtractTcsParameters")); |
| |
| iTSCcapability.ResetCapability(); |
| Oscl_Vector<CPvtMediaCapability*, OsclMemAllocator> capabilityItems; |
| int userInputCapabilities = 0;//1<<PV2WAY_DEFAULT_USER_INPUT_CAPABILITY_INDEX; |
| struct _UserInputCapability *userInputCapability = NULL; |
| |
| iTSCcomponent->ExtractTcsParameters(pTcs); |
| if (pTcs->option_of_multiplexCapability) |
| { |
| PS_MultiplexCapability muxcaps = &pTcs->multiplexCapability; |
| if (muxcaps->index == 2) |
| { |
| PS_H223Capability h223caps = muxcaps->h223Capability; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::ExtractTcsParameters maximumAl2SDUSize=%d,maximumAl3SDUSize=%d", |
| h223caps->maximumAl2SDUSize, h223caps->maximumAl3SDUSize)); |
| iH223->SetSduSize(OUTGOING, h223caps->maximumAl2SDUSize, E_EP_MEDIUM); |
| iH223->SetSduSize(OUTGOING, h223caps->maximumAl3SDUSize, E_EP_HIGH); |
| if ((h223caps->option_of_nsrpSupport == ON) && (h223caps->nsrpSupport == ON)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Remote video caps Option of NSRP support is ON\n")); |
| |
| // switch to NSRP if mux level == 0. If level was 1 or 2, we would have switched after level setup |
| if (iH223->GetMuxLevel() == 0) |
| { |
| iSrp->UseNSRP(true); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Remote video caps Option of NSRP support is OFF\n")); |
| } |
| |
| if (h223caps->option_of_mobileOperationTransmitCapability) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Remote video caps Option of Mobile Transmit Capability is ON\n")); |
| struct _MobileOperationTransmitCapability* mobile_caps = &h223caps->mobileOperationTransmitCapability; |
| if (iTransmitCaps) |
| OSCL_DEFAULT_FREE(iTransmitCaps); |
| iTransmitCaps = (struct _MobileOperationTransmitCapability*)OSCL_DEFAULT_MALLOC(sizeof(struct _MobileOperationTransmitCapability)); |
| oscl_memcpy(iTransmitCaps, mobile_caps, sizeof(struct _MobileOperationTransmitCapability)); |
| } |
| |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::ExtractTcsParameters option_of_maxMUXPDUSizeCapability=%d", |
| h223caps->option_of_maxMUXPDUSizeCapability)); |
| if (h223caps->option_of_maxMUXPDUSizeCapability) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Remote maxMuxPduCapability - %d\n", |
| h223caps->maxMUXPDUSizeCapability)); |
| iMaxMuxPduCapabilityR = h223caps->maxMUXPDUSizeCapability ? true : false; |
| unsigned size = iRequestMaxMuxPduSize; |
| if (iH223->GetMuxLevel() == H223_LEVEL2) |
| size = size > H223_MAX_MUX_PDU_SIZE_LEVEL2 ? H223_MAX_MUX_PDU_SIZE_LEVEL2 : size; |
| if (iMaxMuxPduCapabilityR && size) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m::ExtractTcsParameters Requesting max mux pdu size (%d) from remote", |
| size)); |
| RequestMaxMuxPduSize(size); |
| } |
| } |
| } |
| } |
| |
| if (pTcs->option_of_capabilityTable) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, |
| (0, "TSC_324m: Remote video caps Option of Capability Table is ON, size(%d)\n", |
| pTcs->size_of_capabilityTable)); |
| for (i = 0; i < pTcs->size_of_capabilityTable; ++i) |
| { |
| pCapEntry = pTcs->capabilityTable + i; |
| if (pCapEntry->option_of_capability) |
| { |
| iTSCcapability.ParseTcsCapabilities(pCapEntry->capability, capabilityItems, userInputCapabilities, userInputCapability); |
| } |
| |
| } |
| } |
| iTSCcapability.CreateNewCapability(capabilityItems); |
| userInputCapabilities = userInputCapabilities ? |
| userInputCapabilities : 1 << PV2WAY_DEFAULT_USER_INPUT_CAPABILITY_INDEX; |
| if (iTSC_324mObserver) |
| { |
| iTSC_324mObserver->UserInputCapability(userInputCapabilities); |
| } |
| } |
| |