blob: 7b5facd9b8124ce1da13c2ff49238e1facbdfff1 [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.
* -------------------------------------------------------------------
*/
#ifndef PVRTSP_CLIENT_ENGINE_NODE_H
#define PVRTSP_CLIENT_ENGINE_NODE_H
#ifndef OSCL_BASE_H_INCLUDED
#include "oscl_base.h"
#endif
#ifndef OSCL_UTF8CONV_H
#include "oscl_utf8conv.h"
#endif
#ifndef OSCL_ERROR_CODES_H_INCLUDED
#include "oscl_error_codes.h"
#endif
#ifndef OSCL_SCHEDULER_AO_H_INCLUDED
#include "oscl_scheduler_ao.h"
#endif
#ifndef OSCL_SOCKET_TYPES_H_INCLUDED
#include "oscl_socket_types.h"
#endif
#ifndef OSCL_SOCKET_H_INCLUDED
#include "oscl_socket.h"
#endif
#ifndef OSCL_DNS_H_INCLUDED
#include "oscl_dns.h"
#endif
#ifndef OSCL_STRING_CONTAINERS_H_INCLUDED
#include "oscl_string_containers.h"
#endif
#ifndef PVMF_MEDIA_CLOCK_H_INCLUDED
#include "pvmf_media_clock.h"
#endif
#ifndef OSCL_TIMER_H_INCLUDED
#include "oscl_timer.h"
#endif
#ifndef PVMF_FORMAT_TYPE_H_INCLUDED
#include "pvmf_format_type.h"
#endif
#ifndef PVMF_NODE_INTERFACE_H_INCLUDED
#include "pvmf_node_interface.h"
#endif
#ifndef PVMF_NODE_UTILS_H_INCLUDED
#include "pvmf_node_utils.h"
#endif
#ifndef OSCL_PRIQUEUE_H_INCLUDED
#include "oscl_priqueue.h"
#endif
#ifndef PVMF_SIMPLE_MEDIA_BUFFER_H_INCLUDED
#include "pvmf_simple_media_buffer.h"
#endif
#ifndef OSCL_MEM_MEMPOOL_H_INCLUDED
#include "oscl_mem_mempool.h"
#endif
#ifndef PVLOGGER_H_INCLUDED
#include "pvlogger.h"
#endif
#ifndef PVRTSP_ENGINE_NODE_EXTENSION_INTERFACE_H_INCLUDED
#include "pvrtspenginenodeextensioninterface.h"
#endif
#ifndef RTSP_PAR_COM_MESSAGE_DS_H_
#include "rtsp_par_com_message.h"
#endif
#ifndef RTSP_PARSER_H_
#include "rtsp_parser.h"
#endif
#ifndef SDP_PARSER_H
#include "sdp_parser.h"
#endif
#ifndef PVMF_RTSP_PORT_H_INCLUDED
#include "pvrtsp_client_engine_port.h"
#endif
#ifndef OSCL_FILEIO_H_INCLUDED
#include "oscl_file_io.h"
#endif
#ifndef PVMF_STREAMING_REAL_INTERFACES_INCLUDED
#include "pvmf_streaming_real_interfaces.h"
#endif
#ifndef PAYLOAD_PARSER_H_INCLUDED
#include "payload_parser.h"
#endif
#ifndef PVMF_SM_CONFIG_H_INCLUDED
#include "pvmf_sm_config.h"
#endif
//Default vector reserve size
#define PVMF_RTSP_ENGINE_NODE_COMMAND_VECTOR_RESERVE 10
//Starting value for command IDs
#define PVMF_RTSP_ENGINE_NODE_COMMAND_ID_START 6000
#define MAX_TOTAL_TRACKS 4 /* maximum number of channels per session */
//The RTSP state enumeration
typedef enum
{
STATE_INIT,
STATE_READY,
STATE_PLAYING,
//STATE_RECORDING
} SessionState;
typedef struct _DataChannelInfo
{
uint8 *hexSID;
bool ssrc_is_set;
uint32 ssrc;
bool seqbase_is_set;
uint32 seq;
bool rtptime_is_set;
uint32 rtptime;
int32 offset;
uint32 timescale;
uint32 rtcp_interval;
} DataChannelInfo;
//memory allocator type for this node.
typedef OsclMemAllocator PVRTSPEngineNodeAllocator;
class SessionInfo
{
public:
//bool sdpFlag; //Used to make sure that we read into the mediainfo array after it has been assigned
//SDP_ERROR_CODE sdpErrorCode; //Saves the value returned from the sdp parser
OSCL_HeapString<PVRTSPEngineNodeAllocator> iSessionURL;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iContentBaseURL;//Per session control URL from content base field
OSCL_HeapString<PVRTSPEngineNodeAllocator> iServerName; //could be either DNS or ip address
OSCL_HeapString<PVRTSPEngineNodeAllocator> iProxyName; //could be either DNS or ip address
uint32 iProxyPort;
OsclNetworkAddress iSrvAdd;
bool bExternalSDP; //true if got SDP through external(NOT DESCRIBE) methods
RtspRangeType iReqPlayRange;
RtspRangeType iActPlayRange;
OsclRefCounterMemFrag pSDPBuf;
OsclSharedPtr<SDPInfo> iSDPinfo;
//SDP_Parser *iSDPparser; //Pointer to the SDP_Parser class object
Oscl_Vector<StreamInfo, PVRTSPEngineNodeAllocator> iSelectedStream;
//Form the track to channel association table. This table is used while
//interacting with the media buffer. This table is needed to convert from an index
//based on the number of tracks in the SDP to an index into the number of tracks
//actually selected. For eg, the SDP might have 5 media tracks, but the number of tracks
//that get selected could be 2. If the first track that gets selected corresponds to the third
//track in the SDP list, then the mapping would be 2 -> 0. Similarly, if the second track that
//gets selected is the fifth in the SDP list, the mapping would be 4 -> 1.
//All indices begin from 0.
/*
for(int ii = 0; ii < numberOfChannels; ii++)
{
int sdp_track_id = pSessionInfo->trackSelectionList->getTrackIndex(ii);
pSessionInfo->channel_tbl[sdp_track_id] = ii;
}
*/
int number_of_channels; //Used for interaction with the media buffer class
int channel_tbl[MAX_TOTAL_TRACKS]; //Index from SDP track IDs to tracks actually selected
OSCL_HeapString<PVRTSPEngineNodeAllocator> iSID; //alphanumeric session ID
//OsclMemoryFragment pImgBuf;
bool serverReplyFlag; //Used for communication between the PVStream modules (network module and the task scheduler)
bool getStateFlag; //Used to ensure that the PE's main loop has been called
bool pvServerIsSetFlag; //Used to indicate if we are streaming from PVServer or not
bool tSIDIsSetFlag; //Used to send session id from second SETUP request
uint32 iServerVersionNumber; // Version number of PVSS
int32 prerollDuration; //Saves the jitter buffer size
int32 fwp_counter; //Id of the first returned firewall packet
int32 rtt; //Saves the round trip time for firewall exchange
uint32 roundTripDelay; //Saves the round trip delay for a DESCRIBE request
uint64 clientServerDelay; //Saves the client server delay during a DESCRIBE request
bool pipeLineFlag; //Used to indicate a pipe lined request
OSCL_HeapString<PVRTSPEngineNodeAllocator> iUserAgent;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iUserNetwork;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iDeviceInfo;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iUserID;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iAuthentication;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iExpiration;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iApplicationSpecificString;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iVerification;
OSCL_HeapString<PVRTSPEngineNodeAllocator> iSignature;
enum PVRTSPStreamingType iStreamingType;
bool iSessionCompleted;
void UpdateSessionCompletionStatus(bool aSessionCompleted)
{
iSessionCompleted = aSessionCompleted;
}
public:
SessionInfo():
iProxyPort(0),
bExternalSDP(false),
pvServerIsSetFlag(false),
iServerVersionNumber(0),
roundTripDelay(0),
iSessionCompleted(false)
{
iUserAgent += _STRLIT_CHAR("PVPlayer ");
iReqPlayRange.format = RtspRangeType::INVALID_RANGE;
};
} ;
class RTSPNodeMemDestructDealloc : public OsclDestructDealloc
{
public:
virtual void destruct_and_dealloc(OsclAny *ptr)
{
OSCL_FREE(ptr);
}
};
typedef PVMFGenericNodeCommand<PVRTSPEngineNodeAllocator> PVRTSPEngineCommandBase;
enum TPVMFRtspNodeCommand //TPVMFGenericNodeCommand
{
PVMF_RTSP_NODE_ERROR_RECOVERY = PVMF_GENERIC_NODE_COMMAND_LAST + 1
, PVMF_RTSP_NODE_CANCELALLRESET
};
class PVRTSPEngineCommand: public PVRTSPEngineCommandBase
{
public:
void Construct(PVMFSessionId s, int32 cmd, int32 arg1, int32 arg2, int32& arg3, \
const OsclAny*aContext)
{
PVRTSPEngineCommandBase::Construct(s, cmd, aContext);
iParam1 = (OsclAny*)arg1;
iParam2 = (OsclAny*)arg2;
iParam3 = (OsclAny*) & arg3;
}
void Parse(int32&arg1, int32&arg2, int32*&arg3)
{
arg1 = (int32)iParam1;
arg2 = (int32)iParam2;
arg3 = (int32*)iParam3;
}
virtual bool hipri()
{
if (iCmd == PVMF_RTSP_NODE_ERROR_RECOVERY)
return true;
return PVRTSPEngineCommandBase::hipri();
}
/*
PVMFSessionId iCmdSid;
int32 iCmdId;
TPVMFGenericNodeCommand iCmdType;
OsclAny* iContext;
PVMFPortInterface* iPort;
OsclAny* iData1;
OsclAny* iData2;
OsclAny* iData3;
*/
private:
//PVRTSPEngineCommand(const PVRTSPEngineCommand& aCmd);
};
//Command queue type
typedef PVMFNodeCommandQueue<PVRTSPEngineCommand, PVRTSPEngineNodeAllocator> PVRTSPEngineNodeCmdQ;
class PVRTSPGenericMessageCompareLess
{
public:
/**
* The algorithm used in OsclPriorityQueue needs a compare function
* that returns true when A's priority is less than B's
* @return true if A's priority is less than B's, else false
*/
int compare(RTSPGenericMessage* a, RTSPGenericMessage* b) const
{
return (PVRTSPGenericMessageCompareLess::GetPriority(*a) > PVRTSPGenericMessageCompareLess::GetPriority(*b));
}
/**
* Returns the priority of each command
* @return A 0-based priority number. A lower number indicates lower priority.
*/
static int GetPriority(RTSPGenericMessage &aCmd)
{//for cseq numbers, the low numbers come first. so higher priority
return aCmd.cseq;
}
};
class GetPostCorrelationObject
{
public:
// factory method
static GetPostCorrelationObject *create(OSCL_TCHAR* aFileName = NULL);
// destructor
~GetPostCorrelationObject();
// get post correlation value
uint8 get() const
{
return iGetPostCorrelation;
}
// increase get post correlation value by 1 within [1, 255]
bool update();
private:
// constructor
GetPostCorrelationObject()
{
;
}
bool construct(OSCL_TCHAR* aFileName);
void closeFile();
bool writeToFile();
private:
uint8 iGetPostCorrelation;
bool iFileCreated; // check for the file creation
// File IO stuff
Oscl_FileServer iFs;
Oscl_File iGetPostCorrelationFile;
};
class PVRTSPEngineNode
: public PVInterface,
public PVMFNodeInterface,
public OsclTimerObject,
public OsclSocketObserver,
public OsclDNSObserver,
public OsclTimerObserver,
public OsclMemPoolFixedChunkAllocatorObserver
{
public:
OSCL_IMPORT_REF PVRTSPEngineNode(int32 aPriority);
OSCL_IMPORT_REF virtual ~PVRTSPEngineNode();
//************ begin PVMFNodeInterface
OSCL_IMPORT_REF virtual PVMFStatus ThreadLogon();
OSCL_IMPORT_REF virtual PVMFStatus ThreadLogoff();
/**
GetCapability can be invoked only when after a node is initialized
**/
OSCL_IMPORT_REF virtual PVMFStatus GetCapability(PVMFNodeCapability& aNodeCapability);
/**
* Returns a list of ports currently available in the node that meet the filter criteria
* We can add fancier iterators and filters as needed.
* For now we return all the available ports. If no ports are present, NULL is returned
**/
OSCL_IMPORT_REF virtual PVMFPortIter* GetPorts(const PVMFPortFilter* aFilter = NULL);
/**
* This API is to allow for extensibility of the PVMF Node interface.
* It allows a caller to ask for all UUIDs associated with a particular MIME type.
* If interfaces of the requested MIME type are found within the system, they are added
* to the UUIDs array.
*
* Also added to the UUIDs array will be all interfaces which have the requested MIME
* type as a base MIME type. This functionality can be turned off.
*
* @param aMimeType The MIME type of the desired interfaces
* @param aUuids A vector to hold the discovered UUIDs
* @param aExactUuidsOnly Turns on/off the retrival of UUIDs with aMimeType as a base type
* @param aContext Optional opaque data to be passed back to user with the command response
* @returns A unique command id for asynchronous completion
*/
OSCL_IMPORT_REF virtual PVMFCommandId QueryUUID(PVMFSessionId aSession
, const PvmfMimeString& aMimeType
, Oscl_Vector<PVUuid, PVRTSPEngineNodeAllocator>& aUuids
, bool aExactUuidsOnly = false
, const OsclAny* aContext = NULL);
/**
* This API is to allow for extensibility of the PVMF Node interface.
* It allows a caller to ask for an instance of a particular interface object to be returned.
* The mechanism is analogous to the COM IUnknown method. The interfaces are identified with
* an interface ID that is a UUID as in DCE and a pointer to the interface object is
* returned if it is supported. Otherwise the returned pointer is NULL.
*
* @param aUuid The UUID of the desired interface
* @param aInterfacePtr The output pointer to the desired interface
* @param aContext Optional opaque data to be passed back to user with the command response
* @returns A unique command id for asynchronous completion
*/
OSCL_IMPORT_REF virtual PVMFCommandId QueryInterface(PVMFSessionId aSession
, const PVUuid& aUuid
, PVInterface*& aInterfacePtr
, const OsclAny* aContext = NULL);
/**
* Requests the node to return a port meeting certain criteria for format types and buffering
* capabilities. The node may return a reference to an already created unused port or it may dynamically
* create one if it has the capability to do so. Since there might be some port specific initializations
* that might need to be done for ports created on demand, it will be most flexible to have this as an
* asynchronous API.
* A reference to the port interface is returned with the the command completion. It is passed as an auto ptr
* carrying opaque data that needs to be cast to PVMFPortInterface*
* @exception PVMFErrNotSupported leaves if this is not supported.
**/
OSCL_IMPORT_REF virtual PVMFCommandId RequestPort(PVMFSessionId aSession
, int32 aPortTag
, const PvmfMimeString* aPortConfig = NULL
, const OsclAny* aContext = NULL);
/**
* Releases a port back to the owning node.
* @exception PVMFErrArgument leaves if this node is not the owner.
**/
OSCL_IMPORT_REF virtual PVMFCommandId ReleasePort(PVMFSessionId aSession
, PVMFPortInterface& aPort
, const OsclAny* aContext = NULL);
//Describe,
OSCL_IMPORT_REF virtual PVMFCommandId Init(PVMFSessionId aSession
, const OsclAny* aContext = NULL);
OSCL_IMPORT_REF virtual PVMFCommandId Prepare(PVMFSessionId aSession,
const OsclAny* aContext = NULL);
//Setup, Firewall pkts exchange, Play
/**
* Causes the node to start servicing all connected ports.
**/
OSCL_IMPORT_REF virtual PVMFCommandId Start(PVMFSessionId aSession
, const OsclAny* aContext = NULL);
//Pause
/**
* Causes the node to pause servicing all connected ports without
* discarding un-processed data.
**/
OSCL_IMPORT_REF virtual PVMFCommandId Pause(PVMFSessionId aSession
, const OsclAny* aContext = NULL);
//Teardown
OSCL_IMPORT_REF virtual PVMFCommandId Stop(PVMFSessionId aSession
, const OsclAny* aContext = NULL);
/**
* Resets the node. The node should relinquish all resources that is has acquired as part of the
* initialization process and should be ready to be deleted when this completes.
**/
OSCL_IMPORT_REF virtual PVMFCommandId Reset(PVMFSessionId aSession
, const OsclAny* aContext = NULL);
/**
* Causes the node to stop servicing all connected ports as
* soon as current data is processed.
**/
OSCL_IMPORT_REF virtual PVMFCommandId Flush(PVMFSessionId aSession
, const OsclAny* aContext = NULL);
/**
* Cancel all pending requests. The current request being processed, if any, will also be aborted.
*
* @param aContextData Optional opaque data that will be passed back to the user with the command response
* @returns A unique command id for asynchronous completion
*/
OSCL_IMPORT_REF virtual PVMFCommandId CancelAllCommands(PVMFSessionId aSession
, const OsclAny* aContextData = NULL);
/**
* Cancels pending command with the specified ID.
*
* @param aCmdId Command Id of the command to be cancelled
* @param aContextData Optional opaque data that will be passed back to the user with the command response
* @returns A unique command id for asynchronous completion
*/
OSCL_IMPORT_REF virtual PVMFCommandId CancelCommand(PVMFSessionId aSession
, PVMFCommandId aCmdId
, const OsclAny* aContextData = NULL);
/**
* Ports call this API to report activity to the node.
*
* @param aActivity Information regarding the activity.
*/
OSCL_IMPORT_REF void HandlePortActivity(const PVMFPortActivity& aActivity);
//************ end PVMFNodeInterface
//************ begin PVRTSPEngineNodeExtensionInterface
OSCL_IMPORT_REF virtual void addRef();
OSCL_IMPORT_REF virtual void removeRef(void);
OSCL_IMPORT_REF virtual bool queryInterface(const PVUuid& uuid, PVInterface*& iface);
OSCL_IMPORT_REF virtual PVMFStatus SetStreamingType(PVRTSPStreamingType aType = PVRTSP_3GPP_UDP);
OSCL_IMPORT_REF virtual PVMFStatus SetSessionURL(OSCL_wString& aURL);
OSCL_IMPORT_REF virtual PVMFStatus SetRtspProxy(OSCL_String& aRtspProxyName, uint32 aRtspProxyPort);
OSCL_IMPORT_REF virtual PVMFStatus GetRtspProxy(OSCL_String& aRtspProxyName, uint32& aRtspProxyPort);
OSCL_IMPORT_REF virtual PVMFStatus GetSDP(OsclRefCounterMemFrag& aSDPBuf);
OSCL_IMPORT_REF virtual PVMFStatus SetSDPInfo(OsclSharedPtr<SDPInfo>& aSDPinfo, Oscl_Vector<StreamInfo, PVRTSPEngineNodeAllocator> &aSelectedStream);
OSCL_IMPORT_REF virtual PVMFStatus GetServerInfo(PVRTSPEngineNodeServerInfo& aServerInfo);
OSCL_IMPORT_REF virtual PVMFStatus GetStreamInfo(Oscl_Vector<StreamInfo, PVRTSPEngineNodeAllocator> &aSelectedStream);
OSCL_IMPORT_REF virtual PVMFStatus GetUserAgent(OSCL_wString& aUserAgent);
OSCL_IMPORT_REF virtual PVMFStatus SetClientParameters(OSCL_wString& aUserAgent,
OSCL_wString& aUserNetwork,
OSCL_wString& aDeviceInfo);
OSCL_IMPORT_REF virtual bool IsRdtTransport();
OSCL_IMPORT_REF virtual void SetPortRdtStreamId(PVMFPortInterface* pPort,
int iRdtStreamId);
OSCL_IMPORT_REF virtual void SetRealChallengeCalculator(IRealChallengeGen* pChallengeCalc);
OSCL_IMPORT_REF virtual void SetRdtParser(IPayloadParser* pRdtParser);
OSCL_IMPORT_REF virtual PVMFStatus SetAuthenticationParameters(OSCL_wString& aUserID,
OSCL_wString& aAuthentication,
OSCL_wString& aExpiration,
OSCL_wString& aApplicationSpecificString,
OSCL_wString& aVerification,
OSCL_wString& aSignature);
OSCL_IMPORT_REF virtual PVMFStatus SetRequestPlayRange(const RtspRangeType& aRange);
OSCL_IMPORT_REF virtual PVMFStatus GetActualPlayRange(RtspRangeType& aRange);
OSCL_IMPORT_REF virtual PVMFStatus SetKeepAliveMethod_timeout(int32 aTimeout = 0);
OSCL_IMPORT_REF virtual PVMFStatus SetKeepAliveMethod_use_SET_PARAMETER(bool aUseSetParameter = false);
OSCL_IMPORT_REF virtual PVMFStatus SetKeepAliveMethod_keep_alive_in_play(bool aKeepAliveInPlay = false);
OSCL_IMPORT_REF virtual PVMFStatus GetKeepAliveMethod(int32 &aTimeout, bool &aUseSetParameter, bool &aKeepAliveInPlay);
OSCL_IMPORT_REF virtual PVMFStatus GetRTSPTimeOut(int32 &aTimeout);
OSCL_IMPORT_REF virtual PVMFStatus SetRTSPTimeOut(int32 aTimeout);
//************ end PVRTSPEngineNodeExtensionInterface
//************ begin OsclTimerObserver
OSCL_IMPORT_REF virtual void TimeoutOccurred(int32 timerID, int32 timeoutInfo);
//************ begin OsclSocketObserver
OSCL_IMPORT_REF virtual void HandleSocketEvent(int32 aId, TPVSocketFxn aFxn, TPVSocketEvent aEvent, int32 aError);
//************ end OsclSocketObserver
//************ begin OsclDNSObserver
OSCL_IMPORT_REF virtual void HandleDNSEvent(int32 aId, TPVDNSFxn aFxn, TPVDNSEvent aEvent, int32 aError);
//************ end OsclDNSObserver
//************ begin OsclMemPoolFixedChunkAllocatorObserver
void freechunkavailable(OsclAny*);
//************ end OsclMemPoolFixedChunkAllocatorObserver
void UpdateSessionCompletionStatus(bool aSessionCompleted)
{
iSessionInfo.iSessionCompleted = aSessionCompleted;
}
bool IsSessionCompleted() const
{
return iSessionInfo.iSessionCompleted;
}
typedef struct _SocketEvent
{
int32 iSockId;
TPVSocketFxn iSockFxn;
TPVSocketEvent iSockEvent;
int32 iSockError;
} SocketEvent;
enum PVRTSPEngineState
{
//for async request
PVRTSP_ENGINE_NODE_STATE_IDLE,
PVRTSP_ENGINE_NODE_STATE_DNS_RESOLVING,
PVRTSP_ENGINE_NODE_STATE_CONNECT,
PVRTSP_ENGINE_NODE_STATE_CONNECTING,
PVRTSP_ENGINE_NODE_STATE_HTTP_CLOAKING_SETUP,
PVRTSP_ENGINE_NODE_STATE_SEND_OPTIONS,
PVRTSP_ENGINE_NODE_STATE_SEND_DESCRIBE,
PVRTSP_ENGINE_NODE_STATE_OPTIONS_WAITING,
PVRTSP_ENGINE_NODE_STATE_DESCRIBE_WAITING,
PVRTSP_ENGINE_NODE_STATE_DESCRIBE_DONE,
PVRTSP_ENGINE_NODE_STATE_PROCESS_REST_SETUP,
PVRTSP_ENGINE_NODE_STATE_SETUP_DONE,
PVRTSP_ENGINE_NODE_STATE_WAIT_PLAY,
PVRTSP_ENGINE_NODE_STATE_PLAY_DONE,
PVRTSP_ENGINE_NODE_STATE_WAIT_PAUSE,
PVRTSP_ENGINE_NODE_STATE_PAUSE_DONE,
PVRTSP_ENGINE_NODE_STATE_WAIT_STOP,
PVRTSP_ENGINE_NODE_STATE_WAIT_CALLBACK,
PVRTSP_ENGINE_NODE_STATE_INVALID
} iState;
private:
OsclSharedPtr<PVMFMediaDataImpl> AllocateMediaData(int32& errCode);
Oscl_Vector<SocketEvent, PVRTSPEngineNodeAllocator> iSocketEventQueue;
PVRTSPEngineNodeAllocator iAlloc;
PVMFCommandId iCurrentCmdId;
OsclSocketServ *iSockServ;
//note: this class is for internal use only, but must be public to avoid ADS v1.2 compile error.
public:
//To keep track of current socket op
class SocketState
{
public:
SocketState()
: iPending(false)
, iCanceled(false)
{}
bool iPending;
bool iCanceled;
void Reset()
{
iPending = iCanceled = false;
}
};
private:
//Container for a TCP socket that can connect, send, & recv.
class SocketContainer
{
public:
SocketContainer(): iSocket(NULL)
{}
OsclTCPSocket* iSocket;
SocketState iConnectState;
SocketState iSendState;
SocketState iRecvState;
SocketState iShutdownState;
void Reset(OsclTCPSocket* aSock)
{
iSocket = aSock;
iConnectState.Reset();
iSendState.Reset();
iRecvState.Reset();
iShutdownState.Reset();
}
bool IsBusy()
{
return iSocket
&& (iConnectState.iPending
|| iSendState.iPending
|| iRecvState.iPending
|| iShutdownState.iPending);
}
};
class DnsContainer
{
public:
DnsContainer(): iDns(NULL)
{}
OsclDNS* iDns;
SocketState iState;
bool IsBusy()
{
return (iDns
&& iState.iPending);
}
};
void SetSendPending(SocketContainer&);
void SetRecvPending(SocketContainer&);
SocketContainer iSendSocket, iRecvSocket;
DnsContainer iDNS;
//To keep track of socket reset sequence.
enum TSocketCleanupState
{
ESocketCleanup_Idle
, ESocketCleanup_CancelCurrentOp
, ESocketCleanup_WaitOnCancel
, ESocketCleanup_Shutdown
, ESocketCleanup_WaitOnShutdown
, ESocketCleanup_Delete
};
TSocketCleanupState iSocketCleanupState;
//only for http cloaking, string to store the text to send until send completes
OSCL_HeapString<PVRTSPEngineNodeAllocator> iRecvChannelMsg, iSendChannelMsg;
RTSPParser *iRTSPParser;
RTSPParser::ParserState iRTSPParserState;
RTSPIncomingMessage iIncomingMsg;
uint32 iOutgoingSeq;
bool bNoRecvPending;//an Recv() is pending on RTSP socket
bool bNoSendPending;//a Send() is pending on RTSP socket
PVMFPortInterface* iTheBusyPort;
//OsclMemoryFragment entityBody; //Used to register with RTSP parser
//OsclMemoryFragment embeddedDataMemory; //Used to save embedded binary data
SessionInfo iSessionInfo;
PVLogger* iLogger;
//uint8 iBufEmbedded[2048];
//RTSPEntityBody iEmbeddedData;
PVMFSharedMediaDataPtr iEmbeddedDataPtr;
// Reference counter for extension
uint32 iExtensionRefCount;
uint32 iNumRedirectTrials;
//socket server will callback even if Cancel() is called
//most likely this is the case for OsclDNS as well
//But this is NOT the case for OsclTimer
uint32 iNumHostCallback, iNumConnectCallback, iNumSendCallback, iNumRecvCallback;
int BASE_REQUEST_ID;
static const int REQ_SEND_SOCKET_ID;
static const int REQ_RECV_SOCKET_ID;
int REQ_TIMER_WATCHDOG_ID, REQ_TIMER_KEEPALIVE_ID;
int REQ_DNS_LOOKUP_ID;
const int DEFAULT_RTSP_PORT, DEFAULT_HTTP_PORT;
//these three are in milliseconds
const int TIMEOUT_CONNECT_AND_DNS_LOOKUP, TIMEOUT_SEND, TIMEOUT_RECV;
const int TIMEOUT_SHUTDOWN;
//these two are in seconds
int TIMEOUT_WATCHDOG;
const int TIMEOUT_WATCHDOG_TEARDOWN;
int TIMEOUT_KEEPALIVE;
const int RECOMMENDED_RTP_BLOCK_SIZE;
int setupTrackIndex;
bool bRepositioning;
class PVRTSPErrorContext
{
public:
SocketEvent iErrSockEvent;
PVRTSPEngineState iErrState;
};
//temp string compose buffer for internal use RTSP_MAX_FULL_REQUEST_SIZE
OsclMemoryFragment iRTSPEngTmpBuf;
OsclMemoryFragment iEntityMemFrag;
//OsclRefCounterMemFrag iEntityMemFrag;
// Queue of commands for cancel
PVRTSPEngineNodeCmdQ iCancelCmdQueue;
// Queue of commands user requested
PVRTSPEngineNodeCmdQ iPendingCmdQueue;
//Queue for cmds which are running.
//normally this node will not start processing one command
//until the prior one is finished. However, a hi priority
//command such as Cancel must be able to interrupt a command
//in progress.
PVRTSPEngineNodeCmdQ iRunningCmdQueue;
PVMFPortVector<PVMFRTSPPort, PVRTSPEngineNodeAllocator> iPortVector;
/**
* Queue holding port activity. Only incoming and outgoing msg activity are
* put on the queue. For each port, there should only be at most one activity
* of each type on the queue.
*/
Oscl_Vector<PVMFPortActivity, PVRTSPEngineNodeAllocator> iPortActivityQueue;
PVMFNodeCapability iCapability;
//OsclPriorityQueue<PVRTSPEngineCommand,PVRTSPEngineNodeAllocator,Oscl_Vector<PVRTSPEngineCommand,PVRTSPEngineNodeAllocator>,PVRTSPEngineCommandCompareLess> iPendingCmdQueue;
// Oscl_Vector<PVRTSPEngineAsyncEvent, PVRTSPEngineNodeAllocator> iPendingEvents;
// OsclPriorityQueue<RTSPIncomingMessage,PVRTSPEngineNodeAllocator,Oscl_Vector<RTSPIncomingMessage,PVRTSPEngineNodeAllocator>,PVRTSPGenericMessageCompareLess> iIncomingMsgQueue;
OsclPriorityQueue<RTSPOutgoingMessage*, PVRTSPEngineNodeAllocator, Oscl_Vector<RTSPOutgoingMessage*, PVRTSPEngineNodeAllocator>, PVRTSPGenericMessageCompareLess> iOutgoingMsgQueue;
RTSPOutgoingMessage* iSrvResponse;
bool bSrvRespPending;
OsclTimer<PVRTSPEngineNodeAllocator> *iWatchdogTimer;
int32 iCurrentErrorCode;
PVUuid iEventUUID;
bool bKeepAliveInPlay;
RTSPMethod iKeepAliveMethod;
bool bAddXStrHeader;
OsclMemPoolResizableAllocator *iMediaDataResizableAlloc;
PVMFSimpleMediaBufferCombinedAlloc *iMediaDataImplAlloc;
/* Round trip delay calculation */
PVMFTimebase_Tickcount iRoundTripClockTimeBase;
int32 iErrorRecoveryAttempt;
//uint8 iGetPostCorrelation;
GetPostCorrelationObject *iGetPostCorrelationObject;
private:
PVRTSPEngineNode();
PVRTSPEngineNode& operator = (const PVRTSPEngineNode&);
PVRTSPEngineNode(const PVRTSPEngineNode&);
//OsclActiveObject
virtual void Run();
virtual OsclLeaveCode RunError(OsclLeaveCode aError);
PVMFStatus sendSocketOutgoingMsg(SocketContainer &aSock, RTSPOutgoingMessage &aMsg);
PVMFStatus sendSocketOutgoingMsg(SocketContainer &aSock, const uint8* aSendBuf, uint32 aSendLen);
void ChangeExternalState(TPVMFNodeInterfaceState aNewState);
// Handle command and data events
PVMFCommandId AddCmdToQueue(PVRTSPEngineCommand& aCmd);
bool ProcessCommand(PVRTSPEngineCommand& aCmd);
bool rtspParserLoop(void);
PVMFStatus DispatchCommand(PVRTSPEngineCommand& aCmd);
void MoveCmdToCancelQueue(PVRTSPEngineCommand& aCmd);
PVMFStatus DoInitNode(PVRTSPEngineCommand &aCmd);
PVMFStatus DoPrepareNode(PVRTSPEngineCommand &aCmd);
PVMFStatus DoStartNode(PVRTSPEngineCommand &aCmd);
PVMFStatus DoPauseNode(PVRTSPEngineCommand &aCmd);
PVMFStatus DoStopNode(PVRTSPEngineCommand &aCmd);
PVMFStatus DoResetNode(PVRTSPEngineCommand &aCmd);
PVMFStatus DoQueryUuid(PVRTSPEngineCommand &aCmd);
PVMFStatus DoQueryInterface(PVRTSPEngineCommand &aCmd);
PVMFStatus DoCancelCommand(PVRTSPEngineCommand &aCmd);
PVMFStatus DoCancelAllCommands(PVRTSPEngineCommand &aCmd);
PVMFStatus DoFlush(PVRTSPEngineCommand &aCmd);
PVMFStatus DoErrorRecovery(PVRTSPEngineCommand &aCmd);
PVMFStatus DoRequestPort(PVRTSPEngineCommand &aCmd, PVMFRTSPPort* &aPort);
PVMFStatus DoAddPort(int32 id, bool isMedia, int32 tag, PVMFRTSPPort* &aPort);
PVMFStatus DoReleasePort(PVRTSPEngineCommand &aCmd);
bool FlushPending();
bool ProcessPortActivity();
void QueuePortActivity(const PVMFPortActivity &aActivity);
PVMFStatus ProcessOutgoingMsg(PVMFPortInterface* aPort);
PVMFStatus SendRtspDescribe(PVRTSPEngineCommand &aCmd);
PVMFStatus SendRtspSetup(PVRTSPEngineCommand &aCmd);
PVMFStatus SendRtspPlay(PVRTSPEngineCommand &aCmd);
PVMFStatus SendRtspPause(PVRTSPEngineCommand &aCmd);
PVMFStatus SendRtspTeardown(PVRTSPEngineCommand &aCmd);
void CommandComplete(PVRTSPEngineNodeCmdQ&,
PVRTSPEngineCommand&,
PVMFStatus, OsclAny* aData = NULL,
PVUuid* aEventUUID = NULL,
int32* aEventCode = NULL);
bool parseURL(const OSCL_wString& aURL);
bool parseURL(const char* aURL);
void ChangeInternalState(PVRTSPEngineState aNewTask);
PVMFStatus composeOptionsRequest(RTSPOutgoingMessage&);
PVMFStatus composeDescribeRequest(RTSPOutgoingMessage&);
PVMFStatus composeSetupRequest(RTSPOutgoingMessage &iMsg, StreamInfo &aSelected);
PVMFStatus composePlayRequest(RTSPOutgoingMessage &iMsg);
PVMFStatus composeStopRequest(RTSPOutgoingMessage &iMsg);
PVMFStatus composePauseRequest(RTSPOutgoingMessage &iMsg);
PVMFStatus composeKeepAliveRequest(RTSPOutgoingMessage &aMsg);
PVMFStatus composeGetRequest(RTSPOutgoingMessage &iMsg);
PVMFStatus composePostRequest(RTSPOutgoingMessage &iMsg);
PVMFStatus processIncomingMessage(RTSPIncomingMessage &iIncomingMsg);
PVMFStatus processServerRequest(RTSPIncomingMessage &aMsg);
PVMFStatus processEntityBody(RTSPIncomingMessage &aMsg, OsclMemoryFragment &aEntityMemFrag);
PVMFStatus processCommonResponse(RTSPIncomingMessage &aMsg);
//should merge togather and move to jitter buffer
PVMFStatus composeSessionURL(RTSPOutgoingMessage &aMsg);
PVMFStatus composeMediaURL(int aTrackID, StrPtrLen &aMediaURI);
//PVMFStatus processSDP(OsclMemoryFragment &aSDPBuf, SDPInfo &aSDPinfo);
void ReportErrorEvent(PVMFEventType aEventType,
OsclAny* aEventData = NULL,
PVUuid* aEventUUID = NULL,
int32* aEventCode = NULL);
void ReportInfoEvent(PVMFEventType aEventType,
OsclAny* aEventData = NULL,
PVUuid* aEventUUID = NULL,
int32* aEventCode = NULL);
void MapRTSPCodeToEventCode(RTSPStatusCode aStatusCode,
int32& aEventCode);
//allocate aReqBufSize memory for iEmbeddedData
bool PrepareEmbeddedDataMemory(uint32 aReqBufSize, OsclMemoryFragment &);
bool DispatchEmbeddedData(uint32 aChannelID);
// private members added for real support
bool ibIsRealRDT;
// realchallenge1 string returned by OPTIONS request
OSCL_HeapString<OsclMemAllocator> iRealChallenge1;
// realchallenge2 string to be sent in SETUP request
OSCL_HeapString<OsclMemAllocator> iRealChallenge2;
IRealChallengeGen* ipRealChallengeGen;
IPayloadParser* ipRdtParser;
// allocator for outgoing media frag groups
PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>* ipFragGroupAllocator;
OsclMemPoolFixedChunkAllocator* ipFragGroupMemPool;
/////
bool DispatchEmbeddedRdtData();
bool ibBlockedOnFragGroups;
//bool simpleHttpParser(const uint8 *aBuf, int32 &aLen, bool &aIsStatus200);
PVMFStatus resetSocket(bool aImmediate = false);
void clearOutgoingMsgQueue(void);
void partialResetSessionInfo(void);
bool clearEventQueue(void);
void ResetSessionInfo(void);
PVRTSPEngineNodeExtensionInterface* iExtensionInterface;
};
#endif //PVRTSP_CLIENT_ENGINE_NODE_H