blob: 8b3ce5dc7db62c655fe9276ea2071ee18203c1eb [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 PVMF_PROTOCOLENGINE_NODE_COMMON_H_INCLUDED
#define PVMF_PROTOCOLENGINE_NODE_COMMON_H_INCLUDED
#ifndef OSCL_MEM_MEMPOOL_H_INCLUDED
#include "oscl_mem_mempool.h"
#endif
#ifndef PVMF_MEDIA_DATA_H_INCLUDED
#include "pvmf_media_data.h"
#endif
#ifndef PVMF_SIMPLE_MEDIA_BUFFER_H_INCLUDED
#include "pvmf_simple_media_buffer.h"
#endif
#ifndef PVMF_META_DATA_TYPES_H_INCLUDED
#include "pvmf_meta_data_types.h"
#endif
#ifndef PVMF_MEDIA_MSG_FORMAT_IDS_H_INCLUDED
#include "pvmf_media_msg_format_ids.h"
#endif
#ifndef PVMI_DATASTREAMUSER_INTERFACE_H_INCLUDED
#include "pvmi_datastreamuser_interface.h"
#endif
#ifndef PVLOGGER_H_INCLUDED
#include "pvlogger.h"
#endif
#ifndef PVLOGGER_FILE_APPENDER_H_INCLUDED
#include "pvlogger_file_appender.h"
#endif
#ifndef PVMF_DOWNLOAD_DATA_SOURCE_H_INCLUDED
#include "pvmf_download_data_source.h"
#endif
#ifndef PVMF_SOURCE_CONTEXT_DATA_H_INCLUDED
#include "pvmf_source_context_data.h"
#endif
#ifndef OSCL_TIMER_H_INCLUDED
#include "oscl_timer.h"
#endif
#ifndef PVMF_PROTOCOL_ENGINE_COMMON_H_INCLUDED
#include "pvmf_protocol_engine_common.h"
#endif
#ifndef PVMF_NODE_UTILS_H_INCLUDED
#include "pvmf_node_utils.h"
#endif
#ifndef PVMF_PROTOCOL_ENGINE_NODE_EVENTS_H_INCLUDED
#include "pvmf_protocol_engine_node_events.h"
#endif
#ifndef PVMI_DATA_STREAM_INTERFACE_H_INCLUDED
#include "pvmi_data_stream_interface.h"
#endif
#ifndef PVMF_EVENT_HANDLING_H_INCLUDED
#include "pvmf_event_handling.h"
#endif
#ifndef PVMF_MEDIA_PRESENTATION_INFO_H_INCLUDED
#include "pvmf_media_presentation_info.h"
#endif
#ifndef PVMF_MEMPOOL_H_INCLUDED
#include "pvmf_mempool.h"
#endif
#ifndef PVMF_MEDIA_CLOCK_H_INCLUDED
#include "pvmf_media_clock.h"
#endif
#ifndef PVMI_KVP_H_INCLUDED
#include "pvmi_kvp.h"
#endif
//#define PVMF_PROTOCOL_ENGINE_LOG_MS_STREAMING_OUTPUT
//memory allocator type for this node.
typedef OsclMemAllocator PVMFProtocolEngineNodeAllocator;
// Structure to hold the key string info for
// AAC decnode's capability-and-config
struct PVProtocolEngineNodeKeyStringData
{
char iString[64];
PvmiKvpType iType;
PvmiKvpValueType iValueType;
};
// The number of characters to allocate for the key string
#define PVPROTOCOLENGINENODECONFIG_KEYSTRING_SIZE 128
///////////////////////////////////////////////////////
// For Command implementation
///////////////////////////////////////////////////////
//Default vector reserve size
#define PVMF_PROTOCOLENGINE_NODE_COMMAND_VECTOR_RESERVE 16
//Starting value for command IDs
#define PVMF_PROTOCOLENGINE_NODE_COMMAND_ID_START 6000
enum PVMFProtocolEngineNodeCmdType
{
PVPROTOCOLENGINE_NODE_CMD_SEEK = PVMF_GENERIC_NODE_COMMAND_LAST,
PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH,
PVPROTOCOLENGINE_NODE_CMD_DATASTREAM_REQUEST_REPOSITION
};
enum PVMFProtocolEngineNodeState
{
// this is special node internal state for processing start command
// we set node state as this state before doing the actual work for start
// this is to differentiate the node state between pause and start without completing start command
// this differentiation aims to ignore logging/keep-alive response when start command gets called,
// but hasn't got completed.
// This internal state should be gone when start command gets completed, then node state will change
// to EPVMFNodeStarted
PVMFProtocolEngineNodeState_BeingStarted = EPVMFNodeLastState,
};
//Node command type.
#define PVMFProtocolEngineNodeCommandBase PVMFGenericNodeCommand<PVMFProtocolEngineNodeAllocator> // to remove warning on symbian build
class PVMFProtocolEngineNodeCommand: public PVMFProtocolEngineNodeCommandBase
{
public:
//constructor for Custom2 command
void Construct(PVMFSessionId s, int32 cmd, int32 arg1, int32 arg2, int32& arg3, const OsclAny*aContext)
{
PVMFProtocolEngineNodeCommandBase::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;
}
// Constructor and parser for seek and bitstreamSwitch
void Construct(PVMFSessionId s, int32 cmd,
uint64 aNPTInMS,
uint32& aFirstSeqNumAfterChange,
OsclAny* aContext)
{
PVMFProtocolEngineNodeCommandBase::Construct(s, cmd, aContext);
iNPTInMS = aNPTInMS;
iParam2 = (OsclAny*) & aFirstSeqNumAfterChange;
}
void Parse(uint64& aNPTInMS, uint32*& aFirstSeqNumAfterChange)
{
aNPTInMS = iNPTInMS;
aFirstSeqNumAfterChange = (uint32*)iParam2;
}
// constructor and parser for data stream request, especially reposition request
void Construct(PVMFSessionId s, int32 cmd,
PvmiDataStreamSession aSessionID,
PvmiDataStreamRequest aRequestID,
OsclAny* aRequestData,
PvmiDataStreamCommandId aDataStreamCmdId,
OsclAny* aContext)
{
PVMFProtocolEngineNodeCommandBase::Construct(s, cmd, aContext);
iParam1 = (OsclAny*)aSessionID;
iParam2 = (OsclAny*)((uint32)aRequestID);
iParam3 = aRequestData;
iParam4 = (OsclAny*)aDataStreamCmdId;
}
void Parse(PvmiDataStreamSession& aSessionID, PvmiDataStreamRequest& aRequestID,
OsclAny*& aRequestData, PvmiDataStreamCommandId &aDataStreamCmdId)
{
aSessionID = (PvmiDataStreamSession)iParam1;
aRequestData = iParam3;
aDataStreamCmdId = (PvmiDataStreamCommandId)iParam4;
uint32 requestIDNum = (uint32)iParam2;
aRequestID = (PvmiDataStreamRequest)requestIDNum;
}
void Parse(OsclAny*& aRequestData)
{
aRequestData = iParam3;
}
void Parse(OsclAny*& aRequestData, PvmiDataStreamCommandId &aDataStreamCmdId)
{
aRequestData = iParam3;
aDataStreamCmdId = (PvmiDataStreamCommandId)iParam4;
}
private:
uint64 iNPTInMS;
};
//Command queue type
typedef PVMFNodeCommandQueue<PVMFProtocolEngineNodeCommand, PVMFProtocolEngineNodeAllocator> PVMFProtocolEngineNodeCmdQ;
typedef Oscl_Vector<PVMFSharedMediaMsgPtr, PVMFProtocolEngineNodeAllocator> INPUT_DATA_QUEUE;
typedef Oscl_Vector<OsclRefCounterMemFrag, PVMFProtocolEngineNodeAllocator> OUTPUT_DATA_QUEUE;
typedef Oscl_Vector<OsclRefCounterMemFrag*, PVMFProtocolEngineNodeAllocator> PENDING_OUTPUT_DATA_QUEUE;
// two macros used in the array member and function parameter below
#define PVHTTPDOWNLOADOUTPUT_CONTENTDATA_CHUNKSIZE 8000
#define EVENT_HANDLER_TOTAL 10
enum NetworkTimerType
{
SERVER_RESPONSE_TIMER_ID = 0,
SERVER_INACTIVITY_TIMER_ID,
SERVER_KEEPALIVE_TIMER_ID,
SERVER_RESPONSE_TIMER_ID_FOR_STOPEOS_LOGGING,
// handle data processing in case of no data input (PE node will become idle) for download/progressive streaming,
// so there should be a way to activate PE node to continue data processing if needed
WALL_CLOCK_TIMER_ID,
// a timer to report buffer status periodically, say at every up to 2sec, at least buffer status has to be reported
// which tells our system is running
BUFFER_STATUS_TIMER_ID
};
enum PVHttpProtocol
{
PVHTTPPROTOCOL_PROGRESSIVE_DOWNLOAD = 0,
PVHTTPPROTOCOL_PROGRESSIVE_STREAMING,
PVHTTPPROTOCOL_SHOUTCAST,
PVHTTPPROTOCOL_FASTTRACK_DOWNLOAD,
PVHTTPPROTOCOL_MS_HTTP_STREAMING,
PVHTTPPROTOCOL_UNKNOWN
};
// Forward declarations
class PVMFProtocolEngineNode;
class PVMFProtocolEnginePort;
class PVMIDataStreamSyncInterface;
class PVLogger;
class PVMFLightMediaFragGroupAlloc;
class PVMFMediaPresentationInfo;
class HttpBasedProtocol;
class PVMFProtocolEngineNodeOutput;
class DownloadControlInterface;
class DownloadProgressInterface;
class EventReporter;
class PVDlCfgFile;
class PVDlCfgFileContainer;
class PVMFDownloadDataSourceContainer;
class PVMFProtocolEngineNodeTimer;
class InterfacingObjectContainer;
class UserAgentField;
struct PVProtocolEngineNodeInternalEvent;
class PVProtocolEngineNodeInternalEventHandler;
class PVMFProtocolEnginePort;
class OsclSharedLibrary;
enum NodeObjectType
{
NodeObjectType_InputPortForData = 0,
NodeObjectType_InputPortForLogging,
NodeObjectType_OutPort,
NodeObjectType_InternalEventQueue,
NodeObjectType_Protocol,
NodeObjectType_Output,
NodeObjectType_DownloadControl,
NodeObjectType_DownloadProgress,
NodeObjectType_EventReport,
NodeObjectType_DlCfgFileContainer,
NodeObjectType_DataSourceContainer,
NodeObjectType_Timer,
NodeObjectType_InterfacingObjectContainer,
NodeObjectType_UseAgentField
};
class ProtocolContainerObserver
{
public:
virtual uint32 GetObserverState() = 0;
virtual void SetObserverState(const uint32 aState) = 0;
virtual bool DispatchEvent(PVProtocolEngineNodeInternalEvent *aEvent) = 0;
virtual bool SendMediaCommand(PVMFProtocolEnginePort *aPort, PVUid32 aCmdId, const bool isForLogging = false) = 0;
virtual void ClearRest(const bool aNeedDelete = false) = 0;
virtual void RecheduleDataFlow() = 0;
virtual void SendManualResumeNotificationEvent() = 0;
virtual bool IsRepositionCmdPending() = 0;
virtual PVMFProtocolEngineNodeCommand* FindPendingCmd(int32 aCmdId) = 0;
virtual void CompletePendingCmd(int32 status) = 0;
virtual void CompleteInputCmd(PVMFProtocolEngineNodeCommand& aCmd, int32 status) = 0;
virtual void ErasePendingCmd(PVMFProtocolEngineNodeCommand *aCmd) = 0;
virtual void ReportEvent(PVMFEventType aEventType, OsclAny* aEventData = NULL, const int32 aEventCode = 0, OsclAny* aEventLocalBuffer = NULL, const uint32 aEventLocalBufferSize = 0) = 0;
};
// This class handles protocol initialization for multiple http based protocols,
// and it serves as a friend class of PVMFProtocolEngineNode, and thus helps do
// protocol initialization.
class ProtocolContainer
{
public:
// constructor
OSCL_IMPORT_REF ProtocolContainer(PVMFProtocolEngineNode *aNode = NULL);
virtual ~ProtocolContainer()
{
iDataPathLogger = NULL;
clear();
}
void setObserver(ProtocolContainerObserver *aObserver)
{
iObserver = aObserver;
}
OSCL_IMPORT_REF virtual bool createProtocolObjects();
OSCL_IMPORT_REF virtual void deleteProtocolObjects();
OSCL_IMPORT_REF virtual bool isObjectsReady(); // centralize the info-checking
OSCL_IMPORT_REF virtual void setSupportObject(OsclAny* aSupportObject, const uint32 aType);
virtual PVMFStatus doInit()
{
return PVMFSuccess; // used in PVMFProtocolEngineNode::doInit
}
OSCL_IMPORT_REF virtual PVMFStatus doPrepare(); // used in PVMFProtocolEngineNode::doPrepare, the default implementation is for both 3gpp and fasttrack download
virtual bool doProPrepare()
{
return true; // used only for fasttrack, invoke the call to generate SDP info.
}
virtual int32 doPreStart()
{
return PROCESS_SUCCESS;
}
virtual bool doPause()
{
return true;
}
OSCL_IMPORT_REF virtual PVMFStatus doStop();
OSCL_IMPORT_REF virtual bool doEOS(const bool isTrueEOS = true);
virtual bool doInfoUpdate(const uint32 downloadStatus)
{
OSCL_UNUSED_ARG(downloadStatus); // for now, used for download only, report event and update download control
return true;
}
virtual PVMFStatus doSeek(PVMFProtocolEngineNodeCommand& aCmd)
{
OSCL_UNUSED_ARG(aCmd);
return PVMFSuccess;
}
virtual PVMFStatus doBitstreamSwitch(PVMFProtocolEngineNodeCommand& aCmd)
{
OSCL_UNUSED_ARG(aCmd);
return PVMFSuccess;
}
OSCL_IMPORT_REF virtual bool reconnectSocket(const bool aForceSocketReconnect = true); // used for progressive download and http streaming
virtual bool needSocketReconnect()
{
return true;
}
OSCL_IMPORT_REF virtual void startDataFlowByCommand(const bool needDoSocketReconnect = true);
OSCL_IMPORT_REF virtual void doClear(const bool aNeedDelete = false);
OSCL_IMPORT_REF virtual void doStopClear();
OSCL_IMPORT_REF virtual void doCancelClear();
virtual bool addSourceData(OsclAny* aSourceData)
{
OSCL_UNUSED_ARG(aSourceData);
return true;
}
virtual bool createCfgFile(OSCL_String& aUri)
{
OSCL_UNUSED_ARG(aUri);
return true;
}
virtual bool getProxy(OSCL_String& aProxyName, uint32 &aProxyPort) = 0;
virtual void setHttpVersion(const uint32 aHttpVersion)
{
OSCL_UNUSED_ARG(aHttpVersion);
}
virtual bool handleContentRangeUnmatch()
{
return true;
}
virtual bool downloadUpdateForHttpHeaderAvailable()
{
return true;
}
virtual void setHttpExtensionHeaderField(OSCL_String &aFieldKey, OSCL_String &aFieldValue, const HttpMethod aMethod = HTTP_GET, const bool aPurgeOnRedirect = false)
{
OSCL_UNUSED_ARG(aFieldKey);
OSCL_UNUSED_ARG(aFieldValue);
OSCL_UNUSED_ARG(aMethod);
OSCL_UNUSED_ARG(aPurgeOnRedirect);
}
OSCL_IMPORT_REF virtual void handleTimeout(const int32 timerID);
OSCL_IMPORT_REF virtual bool handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent &aEvent, PVProtocolEngineNodeInternalEventHandler *aEventHandler);
// for fasttrack only
virtual PVMFStatus getMediaPresentationInfo(PVMFMediaPresentationInfo& aInfo)
{
OSCL_UNUSED_ARG(aInfo);
return PVMFSuccess;
}
virtual PVMFStatus selectTracks(PVMFMediaPresentationInfo& aInfo)
{
OSCL_UNUSED_ARG(aInfo);
return PVMFSuccess;
}
//Http status code 409 means low disk space
virtual bool isHTTP409ForLowDiskSpace(const int32 errorCode)
{
OSCL_UNUSED_ARG(errorCode);
return false;
}
// for ms http streaming only
virtual void setLoggingStartInPause(const bool aLoggingStartInPause = true)
{
OSCL_UNUSED_ARG(aLoggingStartInPause);
}
virtual bool isLoggingStartInPause()
{
return false;
}
virtual bool needSendEOSDuetoError(const int32 aErrorCode)
{
OSCL_UNUSED_ARG(aErrorCode);
return false;
}
// for progressive download only
virtual bool needCheckExtraDataComeIn()
{
return false;
}
virtual bool needCheckEOSAfterDisconnectSocket()
{
return false;
}
// for progressive playback (special case of progressive download) only
virtual bool isStreamingPlayback()
{
return false;
}
virtual bool completeRepositionRequest()
{
return false;
}
virtual void checkSendResumeNotification()
{
;
}
virtual void enableInfoUpdate(const bool aEnabled = true)
{
OSCL_UNUSED_ARG(aEnabled);
}
OSCL_IMPORT_REF virtual OsclAny* getObject(const NodeObjectType aObjectType);
virtual void SetSharedLibraryPtr(OsclSharedLibrary* aPtr)
{
iOsclSharedLibrary = aPtr;
}
/**
* Retrieves shared library pointer
* @returns Pointer to the shared library.
**/
virtual OsclSharedLibrary* GetSharedLibraryPtr()
{
return iOsclSharedLibrary;
}
protected:
OSCL_IMPORT_REF virtual PVMFStatus initImpl();
virtual int32 initNodeOutput() = 0;
OSCL_IMPORT_REF bool initProtocol();
virtual bool initProtocol_SetConfigInfo() = 0;
virtual void initDownloadControl()
{
;
}
OSCL_IMPORT_REF uint32 getBitMaskForHTTPMethod(const HttpMethod aMethod = HTTP_GET);
// called by handleTimeout()
virtual bool handleTimeoutInPause(const int32 timerID)
{
OSCL_UNUSED_ARG(timerID);
return false;
}
virtual bool handleTimeoutInDownloadStreamingDone(const int32 timerID)
{
OSCL_UNUSED_ARG(timerID);
return false;
}
// called by doStop()
OSCL_IMPORT_REF virtual void sendSocketDisconnectCmd();
// called by handleTimeout()
OSCL_IMPORT_REF virtual bool ignoreThisTimeout(const int32 timerID);
OSCL_IMPORT_REF virtual void clear();
private:
//called by createProtocolObjects()
bool createNetworkTimer();
// called by handleTimeout()
bool handleTimeoutErr(const int32 timerID);
// called by startDataFlowByCommand()
void checkEOSMsgFromInputPort();
// called by doClear or doCancelClear()
void clearInternalEventQueue();
protected:
PVMFProtocolEngineNode *iNode;
ProtocolContainerObserver *iObserver;
PVLogger *iDataPathLogger;
// hold references for the following node objects
HttpBasedProtocol *iProtocol;
PVMFProtocolEngineNodeOutput *iNodeOutput;
DownloadControlInterface *iDownloadControl;
DownloadProgressInterface *iDownloadProgess;
EventReporter *iEventReport;
PVDlCfgFileContainer *iCfgFileContainer;
PVMFDownloadDataSourceContainer *iDownloadSource;
PVMFProtocolEngineNodeTimer *iNodeTimer;
InterfacingObjectContainer *iInterfacingObjectContainer;
UserAgentField *iUserAgentField;
// pass-in node objects
PVMFProtocolEnginePort *iPortInForData, *iPortInForLogging, *iPortOut;
Oscl_Vector<PVProtocolEngineNodeInternalEvent, PVMFProtocolEngineNodeAllocator> *iInternalEventQueue;
OsclSharedLibrary* iOsclSharedLibrary;
};
////////////////////////////////////////////////////////////////////////////////////
// Using state to handle multiple use cases
enum PVProtocolEngineNodePrcoessingState
{
ProcessingState_Idle = 0,
ProcessingState_NormalDataflow, // normal data flow
// other states are changed to using event
};
static const TPVMFNodeInterfaceState SetStateByCommand[11] =
{
EPVMFNodeInitialized, // PVMF_GENERIC_NODE_INIT=4
EPVMFNodePrepared, // PVMF_GENERIC_NODE_PREPARE=5
EPVMFNodeStarted, // PVMF_GENERIC_NODE_START=6
EPVMFNodePrepared, // PVMF_GENERIC_NODE_STOP=7
EPVMFNodeStarted, // PVMF_GENERIC_NODE_FLUSH=8
EPVMFNodePaused, // PVMF_GENERIC_NODE_PAUSE=9
EPVMFNodeCreated, // PVMF_GENERIC_NODE_RESET=10
EPVMFNodeLastState, // PVMF_GENERIC_NODE_CANCELALLCOMMANDS=11
EPVMFNodeLastState, // PVMF_GENERIC_NODE_CANCELCOMMAND=12
EPVMFNodeStarted, // PVPROTOCOLENGINE_NODE_CMD_SEEK=13,
EPVMFNodeStarted // PVPROTOCOLENGINE_NODE_CMD_BITSTREAM_SWITCH=14
};
////////////////////////////////////////////////////////////////////////////////////
////// PVProtocolEngineNodeInternalEvent definition
////////////////////////////////////////////////////////////////////////////////////
// This structure defines the internal event(constrast to node event) struture, which serves as the basis of
// event-driven handling inside the node
enum PVProtocolEngineNodeInternalEventType
{
// This group of events comes from the callback/feedback from protocol engine
PVProtocolEngineNodeInternalEventType_HttpHeaderAvailable = 0,
PVProtocolEngineNodeInternalEventType_FirstPacketAvailable,
PVProtocolEngineNodeInternalEventType_NormalDataAvailable,
PVProtocolEngineNodeInternalEventType_ProtocolStateComplete,
// This group of events comes from node itself
PVProtocolEngineNodeInternalEventType_EndOfProcessing,
PVProtocolEngineNodeInternalEventType_ServerResponseError_Bypassing,
PVProtocolEngineNodeInternalEventType_ProtocolStateError,
PVProtocolEngineNodeInternalEventType_CheckResumeNotificationMaually,
PVProtocolEngineNodeInternalEventType_OutgoingMsgQueuedAndSentSuccessfully,
// data flow event
PVProtocolEngineNodeInternalEventType_IncomingMessageReady = 9,
PVProtocolEngineNodeInternalEventType_HasExtraInputData,
PVProtocolEngineNodeInternalEventType_OutputDataReady,
PVProtocolEngineNodeInternalEventType_StartDataflowByCommand,
PVProtocolEngineNodeInternalEventType_StartDataflowByBufferAvailability,
PVProtocolEngineNodeInternalEventType_StartDataflowBySendRequestAction,
PVProtocolEngineNodeInternalEventType_StartDataflowByPortOutgoingQueueReady
};
struct PVProtocolEngineNodeInternalEvent
{
PVProtocolEngineNodeInternalEventType iEventId;
OsclAny *iEventInfo; // any other side info except the actual data, such as error code, sequence number(http streaming), seek offset(fasttrack)
OsclAny *iEventData; // actual data for the event
// default constructor
PVProtocolEngineNodeInternalEvent() : iEventId(PVProtocolEngineNodeInternalEventType_HttpHeaderAvailable), iEventInfo(NULL), iEventData(NULL)
{
;
}
// constructor with parameters
PVProtocolEngineNodeInternalEvent(PVProtocolEngineNodeInternalEventType aEventId, OsclAny *aEventInfo, OsclAny *aEventData = NULL)
{
iEventId = aEventId;
iEventInfo = aEventInfo;
iEventData = aEventData;
}
PVProtocolEngineNodeInternalEvent(const ProtocolEngineOutputDataSideInfo &aSideInfo, const OsclAny *aData = NULL)
{
ProtocolEngineOutputDataSideInfo sideInfo = (ProtocolEngineOutputDataSideInfo&) aSideInfo;
iEventId = (PVProtocolEngineNodeInternalEventType)((uint32)sideInfo.iDataType);
iEventInfo = (OsclAny *)sideInfo.iData;
iEventData = (OsclAny *)aData;
}
PVProtocolEngineNodeInternalEvent(PVProtocolEngineNodeInternalEventType aEventId, int32 aInfoCode = 0)
{
iEventId = aEventId;
iEventInfo = (OsclAny *)aInfoCode;
iEventData = NULL;
}
// copy constructor
PVProtocolEngineNodeInternalEvent(const PVProtocolEngineNodeInternalEvent &x)
{
iEventId = x.iEventId;
iEventInfo = x.iEventInfo;
iEventData = x.iEventData;
}
// operator "="
PVProtocolEngineNodeInternalEvent &operator=(const PVProtocolEngineNodeInternalEvent& x)
{
iEventId = x.iEventId;
iEventInfo = x.iEventInfo;
iEventData = x.iEventData;
return *this;
}
};
// this structure defines information needed for EndOfDataProcessingHandler, will be as iEventInfo
struct EndOfDataProcessingInfo
{
bool iSendResumeNotification;
bool iExtraDataComeIn;
bool iSendServerDisconnectEvent;
bool iStreamingDone;
bool iForceStop;
// constructor
EndOfDataProcessingInfo() : iSendResumeNotification(false),
iExtraDataComeIn(false),
iSendServerDisconnectEvent(false),
iStreamingDone(false),
iForceStop(false) {}
bool isValid() const
{
return (iSendResumeNotification ||
iExtraDataComeIn ||
iSendServerDisconnectEvent ||
iStreamingDone ||
iForceStop);
}
void clear()
{
iSendResumeNotification = false;
iExtraDataComeIn = false;
iSendServerDisconnectEvent = false;
iStreamingDone = false;
iForceStop = false;
}
};
// this structure defines information needed for ProtocolStateErrorHandler, will be as iEventInfo
struct ProtocolStateErrorInfo
{
int32 iErrorCode;
// true means using the current iErrorCode, false means using the previous iErrorCode
bool iUseInputErrorCode;
// constructor
ProtocolStateErrorInfo() : iErrorCode(0), iUseInputErrorCode(true)
{
;
}
ProtocolStateErrorInfo(const int32 aErrorCode, const bool aUseInputErrorCode = true) :
iErrorCode(aErrorCode),
iUseInputErrorCode(aUseInputErrorCode)
{
;
}
};
// this structure defines infomation needed for OutgoingMsgSentSuccessHandler, will be as iEventInfo
struct OutgoingMsgSentSuccessInfo
{
PVMFProtocolEnginePort *iPort;
PVMFSharedMediaMsgPtr iMsg;
// constructor
OutgoingMsgSentSuccessInfo(): iPort(NULL)
{
;
}
OutgoingMsgSentSuccessInfo(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg) :
iPort(aPort), iMsg(aMsg)
{
;
}
OutgoingMsgSentSuccessInfo &operator=(const OutgoingMsgSentSuccessInfo& x)
{
iPort = x.iPort;
iMsg = x.iMsg;
return *this;
}
};
// use polymophism to handle variant events
class PVProtocolEngineNodeInternalEventHandler
{
public:
virtual ~PVProtocolEngineNodeInternalEventHandler() {}
virtual bool handle(PVProtocolEngineNodeInternalEvent &aEvent) = 0;
virtual bool completePendingCommand(PVProtocolEngineNodeInternalEvent &aEvent);
// contructor
PVProtocolEngineNodeInternalEventHandler(PVMFProtocolEngineNode *aNode);
protected:
bool isBeingStopped(const int32 aStatus = PROCESS_SUCCESS_END_OF_MESSAGE); // common routine
private:
inline bool isCurrEventMatchCurrPendingCommand(uint32 aCurrEventId);
bool completePendingCommandWithError(PVProtocolEngineNodeInternalEvent &aEvent);
int32 getBasePVMFErrorReturnCode(const int32 errorCode, const bool isForCommandComplete = true);
void handleErrResponse(int32 &aBaseCode, int32 &aErrCode, char* &aEventData, uint32 &aEventDataLen);
void handleAuthenErrResponse(int32 &aErrCode, char* &aEventData, uint32 &aEventDataLen);
void handleRedirectErrResponse(char* &aEventData, uint32 &aEventDataLen);
inline bool isStopCmdPending(); // called by isBeingStopped
inline bool isProtocolStateComplete(const int32 aStatus);
protected:
PVMFProtocolEngineNode *iNode;
PVLogger* iDataPathLogger;
private:
OSCL_HeapString<OsclMemAllocator> iAuthenInfoRealm;
};
// ProtocolStateErrorHandling becomes a little bit more complicated due to the new requirement:
// PE node needs to send EOS to downstream node once error happens during streaming
// Previously, PE node just error out without doing that much stuff. Now for this new requirement,
// PE node needs two rounds error handling in this case, at the first round, probably does nothing but
// storing error code and preparing sending EOS, and then at the second round, does the real error handling
// But for other cases (PDL or streaming doesn't really start), just do error handling
class ProtocolStateErrorHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
ProtocolStateErrorHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode), iErrorCode(0)
{
;
}
private:
int32 parseServerResponseCode(const int32 aErrorCode, bool &isInfoEvent);
// return value: 0 means caller needs to return immediately, not 0 means error
int32 checkRedirectHandling(const int32 aErrorCode);
bool handleRedirect();
bool NeedHandleContentRangeUnmatch(const int32 aErrorCode);
bool handleContentRangeUnmatch();
bool needCompletePendingCommandAtThisRound(PVProtocolEngineNodeInternalEvent &aEvent);
private:
int32 iErrorCode;
};
class HttpHeaderAvailableHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
HttpHeaderAvailableHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
class FirstPacketAvailableHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
FirstPacketAvailableHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
class NormalDataAvailableHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
NormalDataAvailableHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
class ProtocolStateCompleteHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
ProtocolStateCompleteHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
class NormalDataFlowHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
NormalDataFlowHandler(PVMFProtocolEngineNode *aNode) : PVProtocolEngineNodeInternalEventHandler(aNode), iSendSocketReconnect(false)
{
;
}
private:
bool flushDataPostProcessing(const int32 aStatusFlushData);
bool handleEOSLogging();
bool handleEOS(const int32 aStatus);
bool handleEndOfProcessing(const int32 aStatus);
bool dataFlowContinue(const int32 aStatus);
inline bool isReadyGotoNextState(const int32 aStatus); // called by dataFlowContinueOrStop
private:
bool iSendSocketReconnect;
};
class EndOfDataProcessingHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
EndOfDataProcessingHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
private:
void cleanupForStop(PVProtocolEngineNodeInternalEvent &aEvent);
};
class ServerResponseErrorBypassingHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
ServerResponseErrorBypassingHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
// This handler is for PVProtocolEngineNodeInternalEventType_CheckResumeNotificationMaually only. This happens in progressive streaming,
// when MBDS is quickly filled up,and parser node hasn't parsed any data. In this special case, PE node will go idle, but parser node
// may send an internal RequestResumeNotification before parsing any data, then deadlock happens.
class CheckResumeNotificationHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
CheckResumeNotificationHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
class OutgoingMsgSentSuccessHandler : public PVProtocolEngineNodeInternalEventHandler
{
public:
bool handle(PVProtocolEngineNodeInternalEvent &aEvent);
// constructor
OutgoingMsgSentSuccessHandler(PVMFProtocolEngineNode *aNode) :
PVProtocolEngineNodeInternalEventHandler(aNode)
{
;
}
};
////////////////////////////////////////////////////////////////////////////////////
////// PVMFProtocolEngineNodeOutput
////////////////////////////////////////////////////////////////////////////////////
// Observer class for pvHttpStreamingOutput to notify the node when the output buffer is available since
// the memory pool is created inside pvHttpStreamingOutput
class PVMFProtocolEngineNodeOutputObserver
{
public:
virtual ~PVMFProtocolEngineNodeOutputObserver() {}
// notify the node that the output buffer pool is fool, so hold off any data processing
virtual void OutputBufferPoolFull() = 0;
// notify the node that the new output buffer inside the pool is back to available.
virtual void OutputBufferAvailable() = 0;
// notify the node that the new data is already written the file and then download control and status
// should be updated responsively
virtual void ReadyToUpdateDownloadControl() = 0;
// notify the node that a media message has been queued in outgoing message queue successfully
virtual bool QueueOutgoingMsgSentComplete(PVMFProtocolEnginePort *aPort, PVMFSharedMediaMsgPtr &aMsg, const PVMFStatus aStatus) = 0;
};
enum NodeOutputType
{
NodeOutputType_InputPortForData = 0,
NodeOutputType_InputPortForLogging,
NodeOutputType_OutPort,
NodeOutputType_DataStreamFactory
};
// This base class encapsulates port objects (port and data stream)
class PVMFProtocolEngineNodeOutput
{
public:
// set output object such as, input port, output port and data stream factory
OSCL_IMPORT_REF virtual void setOutputObject(OsclAny* aOutputObject, const uint32 aObjectType = NodeOutputType_InputPortForData);
virtual void setConfigInfo(OsclAny* aConfig)
{
OSCL_UNUSED_ARG(aConfig);
}
OSCL_IMPORT_REF virtual bool passDownNewOutputData(OUTPUT_DATA_QUEUE &aOutputQueue, OsclAny* aSideInfo = NULL);
OSCL_IMPORT_REF virtual int32 flushData(const uint32 aOutputType = NodeOutputType_InputPortForData) = 0;
virtual int32 initialize(OsclAny* aInitInfo = NULL) = 0;
virtual int32 reCreateMemPool(uint32 aNumPool)
{
OSCL_UNUSED_ARG(aNumPool);
return PROCESS_SUCCESS;
}
virtual uint32 getNumBuffersInMediaDataPool()
{
return 0;
}
OSCL_IMPORT_REF bool getBuffer(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize = PVHTTPDOWNLOADOUTPUT_CONTENTDATA_CHUNKSIZE);
OSCL_IMPORT_REF virtual void discardData(const bool aNeedReopen = false);
OSCL_IMPORT_REF virtual bool isPortBusy();
// PPB (progressive streaming/playback)
virtual bool releaseMemFrag(OsclRefCounterMemFrag* aFrag)
{
OSCL_UNUSED_ARG(aFrag);
return false;
};
virtual void setContentLength(uint32 aLength)
{
OSCL_UNUSED_ARG(aLength);
};
virtual void dataStreamCommandCompleted(const PVMFCmdResp& aResponse)
{
OSCL_UNUSED_ARG(aResponse);
};
virtual void setDataStreamSourceRequestObserver(PvmiDataStreamRequestObserver* aObserver)
{
OSCL_UNUSED_ARG(aObserver);
};
virtual void flushDataStream()
{
;
}
virtual bool seekDataStream(const uint32 aSeekOffset)
{
OSCL_UNUSED_ARG(aSeekOffset);
return true;
};
// get info from output object to serve as the basis for status update
uint32 getCurrentOutputSize()
{
return iCurrTotalOutputSize;
}
void setCurrentOutputSize(const uint32 aCurrentSize)
{
iCurrTotalOutputSize = aCurrentSize; // used in resume download
}
virtual uint32 getCurrentPlaybackTime()
{
return 0;
}
// in case of progressive streaming, the following two sizes mean available cache size and maximum cache size
virtual uint32 getAvailableOutputSize()
{
return 0xFFFFFFFF;
}
virtual uint32 getMaxAvailableOutputSize()
{
return 0;
}
// constructor and destructor
OSCL_IMPORT_REF PVMFProtocolEngineNodeOutput(PVMFProtocolEngineNodeOutputObserver *aObserver = NULL);
OSCL_IMPORT_REF virtual ~PVMFProtocolEngineNodeOutput();
protected:
// for media data
OSCL_IMPORT_REF PVMFStatus createMemPool();
OSCL_IMPORT_REF void deleteMemPool();
// create media data for composing http request
OSCL_IMPORT_REF bool createMediaData(PVMFSharedMediaDataPtr &aMediaData, uint32 aRequestSize);
OSCL_IMPORT_REF bool sendToDestPort(PVMFSharedMediaDataPtr &aMediaData, PVMFProtocolEnginePort *aPort);
// send the input media data to the port
OSCL_IMPORT_REF virtual bool sendToPort(PVMFSharedMediaDataPtr &aMediaData, const uint32 aPortType = NodeOutputType_InputPortForData);
// reset
OSCL_IMPORT_REF virtual void reset();
protected:
PVMFProtocolEnginePort *iPortIn; // input port connecting to socket node, both for download and http streaming
// Output buffer memory pool
OsclMemPoolFixedChunkAllocator *iContentDataMemPool;
// Allocator for simple media data buffer
PVMFSimpleMediaBufferCombinedAlloc *iMediaDataAlloc;
// Memory pool for simple media data
PVMFMemPoolFixedChunkAllocator iMediaDataMemPool;
PVMFSharedMediaDataPtr iMediaData;
Oscl_Vector<OUTPUT_DATA_QUEUE, PVMFProtocolEngineNodeAllocator> iOutputFramesQueue;
// Mem frags in this queue are being used by the data stream
PENDING_OUTPUT_DATA_QUEUE iPendingOutputDataQueue;
// observer to notify the node when output buffer is available
PVMFProtocolEngineNodeOutputObserver *iObserver;
// current total output size, serves as the basis for status update
uint32 iCurrTotalOutputSize;
PVLogger* iLogger;
PVLogger* iDataPathLogger;
PVLogger* iClockLogger;
};
////////////////////////////////////////////////////////////////////////////////////
////// DownloadControlInterface
////////////////////////////////////////////////////////////////////////////////////
enum DownloadControlSupportObjectType
{
DownloadControlSupportObjectType_SupportInterface = 0,
DownloadControlSupportObjectType_ProgressInterface,
DownloadControlSupportObjectType_EnginePlaybackClock,
DownloadControlSupportObjectType_ProtocolEngine,
DownloadControlSupportObjectType_ConfigFileContainer,
DownloadControlSupportObjectType_SDPInfoContainer,
DownloadControlSupportObjectType_DownloadProgress,
DownloadControlSupportObjectType_OutputObject
};
// The intent of introducing this download ocntrol interface is to make streaming counterpart as a NULL object,
// which remove any error-prone check
class DownloadControlInterface
{
public:
// set download control supporting objects:
virtual void setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType) = 0;
// From PVMFDownloadProgressInterface API pass down
virtual void requestResumeNotification(const uint32 currentNPTReadPosition, bool& aDownloadComplete, bool& aNeedSendUnderflowEvent) = 0;
// check whether to make resume notification; if needed, then make resume notification
virtual void cancelResumeNotification() = 0;
// cancel request of resume notification.
virtual int32 checkResumeNotification(const bool aDownloadComplete = true) = 0;
// return true for the new download progress
// From PVMFDownloadProgressInterface API
virtual void getDownloadClock(OsclSharedPtr<PVMFMediaClock> &aClock) = 0;
// From PVMFDownloadProgressInterface API
virtual void setClipDuration(const uint32 aClipDurationMsec) = 0;
// for auto-resume control for resume download
virtual void setPrevDownloadSize(uint32 aPrevDownloadSize = 0) = 0;
virtual void clear() = 0;
// for progressive playback repositioning
virtual void clearPerRequest() = 0;
virtual bool isDownloadCompletedPerRequest() = 0;
// destructor
virtual ~DownloadControlInterface()
{
;
}
};
////////////////////////////////////////////////////////////////////////////////////
////// DownloadProgressInterface
////////////////////////////////////////////////////////////////////////////////////
// This class encapsulates the download progress update based on different download progress modes
class DownloadProgressInterface
{
public:
virtual void setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType) = 0;
// updata download clock and download progress
virtual bool update(const bool aDownloadComplete = false) = 0;
// return true for the new download progress
virtual bool getNewProgressPercent(uint32 &aProgressPercent) = 0;
// return duration for auto-resume decision
virtual void setClipDuration(const uint32 aClipDurationMsec) = 0;
virtual void setDownloadProgressMode(DownloadProgressMode aMode = DownloadProgressMode_TimeBased) = 0;
virtual ~DownloadProgressInterface()
{
;
}
};
////////////////////////////////////////////////////////////////////////////////////
////// EventReporter
////////////////////////////////////////////////////////////////////////////////////
// This class wraps up sending node info&error event.
enum EventReporterSupportObjectType
{
EventReporterSupportObjectType_DownloadProgress = 0,
EventReporterSupportObjectType_ProtocolEngine,
EventReporterSupportObjectType_ConfigFileContainer,
EventReporterSupportObjectType_NodeInterfacingObject,
EventReporterSupportObjectType_TimerObject,
EventReporterSupportObjectType_OutputObject
};
class EventReporterObserver
{
public:
// TODO: Change the buffer to be const void*.
// TODO: Why do we have event data AND event buffer?
virtual void ReportEvent(PVMFEventType aEventType, OsclAny* aEventData = NULL, const int32 aEventCode = 0, OsclAny* aEventLocalBuffer = NULL, const size_t aEventLocalBufferSize = 0) = 0;
virtual void NotifyContentTooLarge() = 0;
virtual uint32 GetObserverState() = 0;
};
class EventReporter
{
public:
virtual ~EventReporter() {}
// constructor
OSCL_IMPORT_REF EventReporter(EventReporterObserver *aObserver);
virtual void setSupportObject(OsclAny *aSupportObject, EventReporterSupportObjectType aType)
{
OSCL_UNUSED_ARG(aSupportObject);
OSCL_UNUSED_ARG(aType);
}
// major function to walk throught all the node info & error event whether to be sent out
virtual bool checkReportEvent(const uint32 downloadStatus)
{
OSCL_UNUSED_ARG(downloadStatus);
return true;
}
// the content-length event and content too large event, can't fit into the above checkReportEvent() completely
virtual bool checkContentInfoEvent(const uint32 downloadStatus)
{
OSCL_UNUSED_ARG(downloadStatus);
return true;
}
// enable some specific events
virtual void sendDataReadyEvent()
{
;
}
virtual void enableBufferingCompleteEvent()
{
;
}
virtual void sendBufferStatusEvent()
{
;
}
OSCL_IMPORT_REF virtual void clear();
// node is running in start state to kick off the normal downloading and streaming
OSCL_IMPORT_REF void startRealDataflow();
protected:
bool iStarted;
EventReporterObserver *iObserver;
PVLogger *iDataPathLogger;
};
// This class wraps up user agent setting, differentiated in progessive download, fastrack and ms http streaming.
// Any this kind of variation should be wrapped up into an object
class UserAgentField
{
public:
// constructor
UserAgentField() : iOverwritable(false)
{
;
}
OSCL_IMPORT_REF UserAgentField(OSCL_wString &aUserAgent, const bool isOverwritable = false);
OSCL_IMPORT_REF UserAgentField(OSCL_String &aUserAgent, const bool isOverwritable = false);
virtual ~UserAgentField()
{
;
}
// set user agent
OSCL_IMPORT_REF bool setUserAgent(OSCL_wString &aUserAgent, const bool isOverwritable = false);
OSCL_IMPORT_REF bool setUserAgent(OSCL_String &aUserAgent, const bool isOverwritable = false);
// get the actual user agent (not wide string version) based on overwrite mode or replace mode (attach the input user agent to the default one)
OSCL_IMPORT_REF bool getUserAgent(OSCL_String &aUserAgent);
protected:
virtual void getDefaultUserAgent(OSCL_String &aUserAgent) = 0;
protected:
OSCL_HeapString<OsclMemAllocator> iInputUserAgent;
OSCL_HeapString<OsclMemAllocator> iActualUserAgent;
bool iOverwritable;
};
typedef Oscl_Vector<OutgoingMsgSentSuccessInfo, PVMFProtocolEngineNodeAllocator> OutgoingMsgSentSuccessInfoVec;
// This class interfaces between the node and node user, which is in fact a data holder and holds the data set by the node public APIs
// and some output data return to node user
class InterfacingObjectContainer
{
public:
// set and get download format
void setDownloadFormat(PVMFFormatType &aDownloadFormat)
{
iDownloadFormat = (PVMFFormatType)aDownloadFormat;
}
PVMFFormatType getDownloadFormat() const
{
return iDownloadFormat;
}
// set and get url
void setURI(OSCL_String &aUri, const bool aRedirectUri = false)
{
iDownloadURI.setURI(aUri, aRedirectUri);
}
void setURI(OSCL_wString &aUri, const bool aRedirectUri = false)
{
iDownloadURI.setURI(aUri, aRedirectUri);
}
INetURI &getURIObject()
{
return iDownloadURI;
}
void setLoggingURI(OSCL_String &aUri)
{
iLoggingURI.setURI(aUri);
}
void setLoggingURI(OSCL_wString &aUri)
{
iLoggingURI.setURI(aUri);
}
INetURI &getLoggingURIObject()
{
return iLoggingURI;
}
// set and get data stream factory
void setDataStreamFactory(const PVMFDataStreamFactory *aDataStreamFactory)
{
iDataStreamFactory = (PVMFDataStreamFactory *)aDataStreamFactory;
}
PVMFDataStreamFactory *getDataStreamFactory()
{
return iDataStreamFactory;
}
// set and get stream parameters in http streaming
void setStreamParams(PVMFProtocolEngineNodeMSHTTPStreamingParams &aStreamParams)
{
iStreamParams = aStreamParams;
}
PVProtocolEngineMSHttpStreamingParams *getStreamParams()
{
return &iStreamParams;
}
//set fast cache setting
void SetAccelBitrate(uint32 aAccelBitrate)
{
iStreamParams.iAccelBitrate = aAccelBitrate;
}
void SetAccelDuration(uint32 aAccelDuration)
{
iStreamParams.iAccelDuration = aAccelDuration;
}
//set max streaming size
void SetMaxHttpStreamingSize(uint32 aMaxHttpStreamingSize)
{
iStreamParams.iMaxHttpStreamingSize = aMaxHttpStreamingSize;
}
// set and get number of buffers in media message allocator in http streaming
void setMediaMsgAllocatorNumBuffers(const uint32 aNumBuffersInAllocator)
{
iNumBuffersInAllocator = aNumBuffersInAllocator;
}
uint32 getMediaMsgAllocatorNumBuffers() const
{
return iNumBuffersInAllocator;
}
// set and get number of redirect trials
void setNumRedirectTrials(const uint32 aNumRedirectTrials)
{
iNumRedirectTrials = aNumRedirectTrials;
}
void setCurrNumRedirectTrials(const uint32 aCurrNumRedirectTrials)
{
iCurrRedirectTrials = aCurrNumRedirectTrials;
}
uint32 getNumRedirectTrials() const
{
return iNumRedirectTrials;
}
uint32 getCurrNumRedirectTrials() const
{
return iCurrRedirectTrials;
}
// set and get http header
// return the actual http header length, 0 means no header
OSCL_IMPORT_REF uint32 setHttpHeader(OUTPUT_DATA_QUEUE &aHttpHeader);
void getHTTPHeader(uint8*& aHeader, uint32& aHeaderLen)
{
aHeader = (uint8*)iHttpHeaderBuffer;
aHeaderLen = iHttpHeaderLength;
}
// set and get file size
void setFileSize(const uint32 aFileSize)
{
iFileSize = aFileSize;
}
uint32 getFileSize() const
{
return iFileSize;
}
// socket connect flags
void updateSocketConnectFlags(const bool isEOS)
{
if (!iCurrSocketConnection && !isEOS) iSocketReconnectCmdSent = false; // when connnection becomes from down (EOS) to up, clear the flag of sending socket reconnect command
iPrevSocketConnection = iCurrSocketConnection;
iCurrSocketConnection = !isEOS;
}
bool isSocketConnectionUp() const
{
return iCurrSocketConnection;
}
bool isPrevSocketConnectionUp() const
{
return iPrevSocketConnection;
}
bool isSocketReconnectCmdSent() const
{
return iSocketReconnectCmdSent;
}
void setSocketReconnectCmdSent(const bool aSocketReconnectCmdSent = true)
{
iSocketReconnectCmdSent = aSocketReconnectCmdSent;
}
bool ignoreCurrentInputData() const
{
return isCurrentInputDataUnwanted;
}
void setInputDataUnwanted(const bool aInputDataUnwanted = true)
{
isCurrentInputDataUnwanted = aInputDataUnwanted;
}
// KeepAlive timeout
void setKeepAliveTimeout(const uint32 aTimeout)
{
iKeepAliveTimeout = aTimeout;
}
uint32 getKeepAliveTimeout() const
{
return iKeepAliveTimeout;
}
// Streaming proxy
OSCL_IMPORT_REF bool setStreamingProxy(OSCL_wString& aProxyName, const uint32 aProxyPort = DEFAULT_HTTP_PORT_NUMBER);
void getStreamingProxy(OSCL_String& aProxyName, uint32 &aProxyPort)
{
aProxyName = iProxyName;
aProxyPort = iProxyPort;
}
// flag of disabling HTTP HEAD request
void setHttpHeadRequestDisabled(const bool aDisableHeadRequest = true)
{
iDisableHeadRequest = aDisableHeadRequest;
}
bool getHttpHeadRequestDisabled() const
{
return iDisableHeadRequest;
}
// maximum ASF header size
void setMaxASFHeaderSize(const uint32 aMaxASFHeaderSize)
{
iMaxASFHeaderSize = aMaxASFHeaderSize;
}
uint32 getMaxASFHeaderSize() const
{
return iMaxASFHeaderSize;
}
// latest packet number just sent to downstream node successfully
void setLatestPacketNumSent(const uint32 aPacketNum)
{
iLatestDataPacketNumSent = aPacketNum;
}
uint32 getLatestPacketNumSent() const
{
return iLatestDataPacketNumSent;
}
// user-id and password for HTTP authentication
void setUserAuthInfo(OSCL_String &aUserID, OSCL_String &aPasswd)
{
if (aUserID.get_size() > 0)
{
iStreamParams.iUserID = OSCL_HeapString<OsclMemAllocator> (aUserID.get_cstr(), aUserID.get_size());
}
if (aPasswd.get_size() > 0)
{
iStreamParams.iUserPasswd = OSCL_HeapString<OsclMemAllocator> (aPasswd.get_cstr(), aPasswd.get_size());
}
}
OSCL_IMPORT_REF void setNumBuffersInMediaDataPoolSMCalc(uint32 aVal);
uint32 getNumBuffersInMediaDataPoolSMCalc() const
{
return iNumBuffersInMediaDataPoolSMCalc;
}
// iOutputPortConnected
void setOutputPortConnect(const bool aConnected = true)
{
iOutputPortConnected = aConnected;
}
bool getOutputPortConnect() const
{
return iOutputPortConnected;
}
// iCancelCmdHappened
void setCancelCmdHappened(const bool aCancelCmdHappened = true)
{
iCancelCmdHappened = aCancelCmdHappened;
}
bool getCancelCmdHappened() const
{
return iCancelCmdHappened;
}
// iEOPInfo
EndOfDataProcessingInfo *getEOPInfo()
{
return &iEOPInfo;
}
// protocol state complete info
void setProtocolStateCompleteInfo(const ProtocolStateCompleteInfo &aInfo, const bool aForceSet = false)
{
if (!aForceSet)
{
if (aInfo.isDownloadStreamingDone) iProtocolStateCompleteInfo.isDownloadStreamingDone = true;
if (aInfo.isWholeSessionDone) iProtocolStateCompleteInfo.isWholeSessionDone = true;
if (aInfo.isEOSAchieved) iProtocolStateCompleteInfo.isEOSAchieved = true;
}
else
{
iProtocolStateCompleteInfo.isDownloadStreamingDone = aInfo.isDownloadStreamingDone;
iProtocolStateCompleteInfo.isWholeSessionDone = aInfo.isWholeSessionDone;
iProtocolStateCompleteInfo.isEOSAchieved = aInfo.isEOSAchieved;
}
}
ProtocolStateCompleteInfo *getProtocolStateCompleteInfo()
{
return &iProtocolStateCompleteInfo;
}
OutgoingMsgSentSuccessInfoVec *getOutgoingMsgSentSuccessInfoVec()
{
return &iOutgoingMsgSentSuccessInfoVec;
}
bool isDownloadStreamingDone()
{
return iProtocolStateCompleteInfo.isDownloadStreamingDone;
}
bool isWholeSessionDone()
{
return iProtocolStateCompleteInfo.isWholeSessionDone;
}
bool isEOSAchieved()
{
return iProtocolStateCompleteInfo.isEOSAchieved;
}
void setTruncatedForLimitSize(const bool aTruncatedForLimitSize = false)
{
iTruncatedForLimitSize = aTruncatedForLimitSize;
}
bool getTruncatedForLimitSize() const
{
return iTruncatedForLimitSize;
}
// constructor
InterfacingObjectContainer();
~InterfacingObjectContainer()
{
clear();
iOutgoingMsgSentSuccessInfoVec.clear();
}
// clear
void clear()
{
iHttpHeaderLength = 0;
iFileSize = 0;
iSocketReconnectCmdSent = false;
iCurrRedirectTrials = 0;
isCurrentInputDataUnwanted = true; // when clear(), treat all the input data unwanted (that needs to be ignored), let command and event to enable it
iProcessingDone = false;
iKeepAliveTimeout = 0;
iDisableHeadRequest = true; // changed on the request of Japan
iMaxASFHeaderSize = 0;
iCancelCmdHappened = false;
iTruncatedForLimitSize = false;
iProtocolStateCompleteInfo.clear();
}
private:
PVMFFormatType iDownloadFormat;
// set by SetSourceInitializationData()
INetURI iDownloadURI;
// set by SetLoggingURL
INetURI iLoggingURI;
// set by PassDatastreamFactory()
PVMFDataStreamFactory *iDataStreamFactory;
// set by SetStreamParams()
PVProtocolEngineMSHttpStreamingParams iStreamParams;
// set by SetMediaMsgAllocatorNumBuffers()
uint32 iNumBuffersInAllocator;
// set by SetNumRedirectTrials
uint32 iNumRedirectTrials;
uint32 iCurrRedirectTrials;
uint32 iNumBuffersInMediaDataPoolSMCalc;
// get from GetHTTPHeader()
char iHttpHeaderBuffer[PVHTTPDOWNLOADOUTPUT_CONTENTDATA_CHUNKSIZE+1]; // to hold http header
uint32 iHttpHeaderLength;
// get from GetFileSize()
uint32 iFileSize;
// socket connect flags
bool iCurrSocketConnection; // true means the connection is up and on ; false means the connection is downn
bool iPrevSocketConnection; // the status of previous socket connection
bool iSocketReconnectCmdSent; // flag to record whether the socket reconnect command is sent
// this flag is introduced to ignore unwanted incoming messages in certain scenarios,
// such as stop/reset/cancel, protocol state complete/error, while init/prepare/start command would disable
// this flag
bool isCurrentInputDataUnwanted;
bool iProcessingDone; // work as a global variable
uint32 iKeepAliveTimeout;
// streaming proxy and port
OSCL_HeapString<OsclMemAllocator> iProxyName;
uint32 iProxyPort;
bool iDisableHeadRequest;
uint32 iMaxASFHeaderSize;
uint32 iLatestDataPacketNumSent;
// the connection status between PE node output port and downstream(JB) node input port
// this flag will help sending EOS or not
bool iOutputPortConnected;
bool iCancelCmdHappened;
// work as a global variable
EndOfDataProcessingInfo iEOPInfo;
ProtocolStateCompleteInfo iProtocolStateCompleteInfo;
OutgoingMsgSentSuccessInfoVec iOutgoingMsgSentSuccessInfoVec;
// This flag mean data-size reach limitation or not
// true : data reached limitation
// false: data don't reach limitation
bool iTruncatedForLimitSize;
};
////////////////////////////////////////////////////////////////////////////////////
////// PVMFProtocolEngineNodeTimer
////////////////////////////////////////////////////////////////////////////////////
// This class wraps OsclTimer<allocator> to hide some details and make call more expressive
struct TimerUnit
{
uint32 iTimerID;
uint32 iTimeout;
// constructor
TimerUnit() : iTimerID(0), iTimeout(0)
{
;
}
TimerUnit(const uint32 aTimerID, const uint32 aTimeout) : iTimerID(aTimerID), iTimeout(aTimeout)
{
;
}
};
class PVMFProtocolEngineNodeTimer
{
public:
// factory and destructor
OSCL_IMPORT_REF static PVMFProtocolEngineNodeTimer* create(OsclTimerObserver *aObserver);
OSCL_IMPORT_REF ~PVMFProtocolEngineNodeTimer();
// register and set timer id and timeout value
// note that if aTimeout=0, that means using the internal default one
OSCL_IMPORT_REF void set(const uint32 aTimerID, const int32 aTimeout = 0);
// get the timeout value for specific timer id. If not set, return default value
// if input timer id is not registered, will return 0xffffffff
OSCL_IMPORT_REF uint32 getTimeout(const uint32 aTimerID);
// start the timer with optional new timeout value, aTimeout=0 means using the existing one
// if the timer id doesn't exist, it will return failure, which means set() has to be called before start()
OSCL_IMPORT_REF bool start(const uint32 aTimerID, const int32 aTimeout = 0);
OSCL_IMPORT_REF void cancel(const uint32 aTimerID);
OSCL_IMPORT_REF void clear();
// clear all the timers except the timer with the given timer ID
OSCL_IMPORT_REF void clearExcept(const uint32 aTimerID);
private:
// constructor
PVMFProtocolEngineNodeTimer() : iWatchdogTimer(NULL)
{
;
}
bool construct(OsclTimerObserver *aObserver);
uint32 getDefaultTimeout(const uint32 aTimerID);
uint32 getTimerVectorIndex(const uint32 aTimerID);
private:
OsclTimer<PVMFProtocolEngineNodeAllocator> *iWatchdogTimer;
Oscl_Vector<TimerUnit, PVMFProtocolEngineNodeAllocator> iTimerVec;
};
#endif