blob: ec6019ebb452b742ef1a07c64f438dcff8ed2684 [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_DOWNLOAD_COMMON_H_INCLUDED
#define PVMF_PROTOCOLENGINE_NODE_DOWNLOAD_COMMON_H_INCLUDED
#ifndef PVMF_PROTOCOLENGINE_NODE_COMMON_H_INCLUDED
#include "pvmf_protocol_engine_node_common.h"
#endif
////////////////////////////////////////////////////////////////////////////////////
////// DownloadContainer
////////////////////////////////////////////////////////////////////////////////////
class DownloadContainer : public ProtocolContainer
{
public:
// constructor
DownloadContainer(PVMFProtocolEngineNode *aNode = NULL);
virtual ~DownloadContainer()
{
;
}
virtual void deleteProtocolObjects();
virtual int32 doPreStart();
virtual bool doPause();
virtual PVMFStatus doStop();
virtual void doClear(const bool aNeedDelete = false);
virtual void doCancelClear();
virtual bool doInfoUpdate(const uint32 downloadStatus);
virtual bool addSourceData(OsclAny* aSourceData);
virtual bool createCfgFile(OSCL_String& aUri);
virtual bool getProxy(OSCL_String& aProxyName, uint32 &aProxyPort);
virtual void setHttpVersion(const uint32 aHttpVersion);
virtual void setHttpExtensionHeaderField(OSCL_String &aFieldKey,
OSCL_String &aFieldValue,
const HttpMethod aMethod,
const bool aPurgeOnRedirect);
virtual bool handleContentRangeUnmatch();
virtual bool downloadUpdateForHttpHeaderAvailable();
virtual bool isStreamingPlayback();
virtual bool handleProtocolStateComplete(PVProtocolEngineNodeInternalEvent &aEvent, PVProtocolEngineNodeInternalEventHandler *aEventHandler);
virtual void checkSendResumeNotification();
protected:
virtual int32 initNodeOutput();
virtual bool initProtocol_SetConfigInfo();
virtual void initDownloadControl();
virtual void updateDownloadControl(const bool isDownloadComplete = false);
virtual bool isDownloadComplete(const uint32 downloadStatus) const
{
return (downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE ||
downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED ||
downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA ||
downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT);
}
virtual bool ignoreThisTimeout(const int32 timerID);
virtual bool needToCheckResumeNotificationMaually()
{
return iNeedCheckResumeNotificationManually;
}
private:
//called by createProtocolObjects()
bool createNetworkTimer();
bool createEventHandlers();
protected:
bool iForceSocketReconnect;
bool iNeedCheckResumeNotificationManually;
};
////////////////////////////////////////////////////////////////////////////////////
////// pvHttpDownloadOutput
////////////////////////////////////////////////////////////////////////////////////
// This derived class adds data stream output
struct DownloadOutputConfig
{
bool isResumeDownload;
bool isRangeSupport;
bool isNeedOpenDataStream;
// constructor
DownloadOutputConfig() : isResumeDownload(false),
isRangeSupport(true),
isNeedOpenDataStream(true)
{
;
}
};
class pvHttpDownloadOutput : public PVMFProtocolEngineNodeOutput
{
public:
void setOutputObject(OsclAny* aOutputObject, const uint32 aObjectType = NodeOutputType_InputPortForData);
int32 initialize(OsclAny* aInitInfo = NULL);
virtual int32 flushData(const uint32 aOutputType = NodeOutputType_InputPortForData);
virtual void discardData(const bool aNeedReopen = false);
uint32 getAvailableOutputSize();
uint32 getMaxAvailableOutputSize();
// constructor and destructor
pvHttpDownloadOutput(PVMFProtocolEngineNodeOutputObserver *aObserver = NULL);
virtual ~pvHttpDownloadOutput();
protected:
// write data to data stream object
// return~0=0xffffffff for error.
uint32 writeToDataStream(OUTPUT_DATA_QUEUE &aOutputQueue);
bool writeToDataStream(uint8 *aBuffer, uint32 aBufferLen);
virtual int32 openDataStream(OsclAny* aInitInfo);
// reset
virtual void reset();
protected:
PVMFDataStreamFactory *iDataStreamFactory;
PVMIDataStreamSyncInterface *iDataStream;
PvmiDataStreamSession iSessionID; // PvmiDataStreamSession = int32
bool isOpenDataStream;
uint32 iCounter; // for debugging purpose
};
////////////////////////////////////////////////////////////////////////////////////
////// pvDownloadControl
////////////////////////////////////////////////////////////////////////////////////
// This class does auto-resume control and download progress update for event report
class DownloadProgressInterface;
class pvDownloadControl : public DownloadControlInterface
{
public:
// constructor, may leave for creating download clock
pvDownloadControl();
virtual ~pvDownloadControl()
{
clearBody();
}
// set download control supporting objects:
// PVMFFormatProgDownloadSupportInterface object,
// PVMFDownloadProgressInterface object,
// engine playback clock object,
// protocol engine object,
// DownloadProgressInterface object, (to get the clip duraton)
// PVMFProtocolEngineNodeOutput object
void setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType);
// From PVMFDownloadProgressInterface API pass down
virtual void requestResumeNotification(const uint32 currentNPTReadPosition, bool& aDownloadComplete, bool& aNeedSendUnderflowEvent);
void cancelResumeNotification();
// check whether to make resume notification; if needed, then make resume notification
// Return value: 1 means making resume notification normally (underflow->auto resume),
// 2 means making resume notification for download complete
// 0 means anything else
virtual int32 checkResumeNotification(const bool aDownloadComplete = true);
// From PVMFDownloadProgressInterface API
virtual void getDownloadClock(OsclSharedPtr<PVMFMediaClock> &aClock)
{
OSCL_UNUSED_ARG(aClock);
}
// From PVMFDownloadProgressInterface API
void setClipDuration(const uint32 aClipDurationMsec)
{
iClipDurationMsec = aClipDurationMsec;
}
void setPrevDownloadSize(uint32 aPrevDownloadSize = 0)
{
iPrevDownloadSize = aPrevDownloadSize;
}
void clear();
// clear several fields for progressive playback repositioning
virtual void clearPerRequest()
{
;
}
// checks if download has completed
bool isDownloadCompletedPerRequest()
{
return iDownloadComplete;
}
protected:
// simple routine to focus on sending resume notification only
virtual void sendResumeNotification(const bool aDownloadComplete);
void sendDownloadCompleteNotification();
// auto-resume playback decision
bool isResumePlayback(const uint32 aDownloadRate, const uint32 aCurrDownloadSize, const uint32 aFileSize);
// create iDlProgressClock, will leave when memory allocation fails
void createDownloadClock();
virtual bool updateDownloadClock() = 0;
// ready means, download clock has been created, and all the objects have passed down
bool isInfoReady()
{
return !(iDlProgressClock.GetRep() == NULL ||
iProtocol == NULL ||
iDownloadProgress == NULL ||
iNodeOutput == NULL);
};
// called by isResumePlayback()
virtual bool isDlAlgoPreConditionMet(const uint32 aDownloadRate,
const uint32 aDurationMsec,
const uint32 aCurrDownloadSize,
const uint32 aFileSize);
// update duration by new playback rate, called by checkAutoResumeAlgoWithConstraint
virtual bool checkNewDuration(const uint32 aCurrDurationMsec, uint32 &aNewDurationMsec)
{
aNewDurationMsec = aCurrDurationMsec;
return true;
}
// called by checkAutoResumeAlgoWithConstraint()
virtual bool approveAutoResumeDecisionShortCut(const uint32 aCurrDownloadSize,
const uint32 aDurationMsec,
const uint32 aPlaybackTimeMsec,
uint32 &aPlaybackRemainingTimeMsec)
{
OSCL_UNUSED_ARG(aCurrDownloadSize);
OSCL_UNUSED_ARG(aDurationMsec);
OSCL_UNUSED_ARG(aPlaybackTimeMsec);
OSCL_UNUSED_ARG(aPlaybackRemainingTimeMsec);
return false;
}
// No constraint: for file size/clip duration/clip bitrate(i.e. playback rate), one of them must be unavailable, except
// file size and clip duration are available, but clip bitrate is unavailable. This only applies on PDL
virtual bool checkAutoResumeAlgoNoConstraint(const uint32 aCurrDownloadSize,
const uint32 aFileSize,
uint32 &aDurationMsec)
{
OSCL_UNUSED_ARG(aCurrDownloadSize);
OSCL_UNUSED_ARG(aFileSize);
OSCL_UNUSED_ARG(aDurationMsec);
return false;
}
// adding buffer constraint for the algo, i.e. if buffer constraint meets (or buffer overflows), auto-resume should kick off.
virtual bool isOutputBufferOverflow()
{
return false;
}
// handle overflow issue: // result = x*1000/y
uint32 divisionInMilliSec(const uint32 x, const uint32 y);
protected:
// called by checkResumeNotification()
bool checkDownloadCompleteForResumeNotification(const bool aDownloadComplete);
// called by isResumePlayback()
// with contraint: file size and clip duration are both available
bool checkAutoResumeAlgoWithConstraint(const uint32 aDownloadRate,
const uint32 aRemainingDownloadSize,
const uint32 aDurationMsec,
const uint32 aFileSize);
// use fixed-point calculation to replace the float-point calculation: aRemainingDLSize<0.0009*aDownloadRate*aRemainingPlaybackTime
bool approveAutoResumeDecision(const uint32 aRemainingDLSize,
const uint32 aDownloadRate,
const uint32 aRemainingPlaybackTime);
// old algorithm
bool isResumePlaybackWithOldAlg(const uint32 aDownloadRate,
const uint32 aRemainingDownloadSize);
// set file size to parser node for the new API, setFileSize()
void setFileSize(const uint32 aFileSize);
bool getPlaybackTimeFromEngineClock(uint32 &aPlaybackTime);
private:
void updateFileSize();
void clearBody();
protected:
// download control
PVMFTimebase_Tickcount iEstimatedServerClockTimeBase;
OsclSharedPtr<PVMFMediaClock> iDlProgressClock;
PVMFMediaClock* iCurrentPlaybackClock;
PVMFFormatProgDownloadSupportInterface *iProgDownloadSI;
HttpBasedProtocol *iProtocol;
DownloadProgressInterface *iDownloadProgress;
PVMFProtocolEngineNodeOutput *iNodeOutput;
PVDlCfgFileContainer *iCfgFileContainer;
bool iPlaybackUnderflow;
bool iDownloadComplete;
bool iRequestResumeNotification;
bool iFirstResumeNotificationSent;
uint32 iCurrentNPTReadPosition;
uint32 iClipDurationMsec;
uint32 iPlaybackByteRate;
uint32 iPrevDownloadSize;
uint32 iFileSize;
bool iDlAlgoPreConditionMet;
bool iSetFileSize;
bool iSendDownloadCompleteNotification;
uint32 iClipByterate;
PVLogger* iDataPathLogger;
};
////////////////////////////////////////////////////////////////////////////////////
////// DownloadProgress
////////////////////////////////////////////////////////////////////////////////////
class DownloadProgress : public DownloadProgressInterface
{
public:
// cosntructor and destructor
DownloadProgress();
virtual ~DownloadProgress()
{
reset();
}
// set download progress supporting objects:
// PVMFFormatProgDownloadSupportInterface object,
// protocol engine object,
// config file object, (for progressive download only)
// track selction container (for fastrack download only)
// PVMFProtocolEngineNodeOutput object (for fasttrack download only)
virtual void setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType);
// updata download progress
bool update(const bool aDownloadComplete = false);
// return true for the new download progress
bool getNewProgressPercent(uint32 &aProgressPercent);
// return duration regardless of the difference between progressive download and fasttrack download
void setClipDuration(const uint32 aClipDurationMsec)
{
iDurationMsec = aClipDurationMsec;
}
virtual void setDownloadProgressMode(DownloadProgressMode aMode = DownloadProgressMode_TimeBased)
{
OSCL_UNUSED_ARG(aMode);
}
protected:
virtual uint32 getClipDuration();
virtual bool updateDownloadClock(const bool aDownloadComplete) = 0;
virtual bool calculateDownloadPercent(uint32 &aDownloadProgressPercent);
virtual void reset();
protected:
HttpBasedProtocol *iProtocol;
PVMFFormatProgDownloadSupportInterface *iProgDownloadSI;
PVMFProtocolEngineNodeOutput *iNodeOutput;
//for progress reports
uint32 iCurrProgressPercent;
uint32 iPrevProgressPercent;
uint32 iDownloadNPTTime;
uint32 iDurationMsec;
};
////////////////////////////////////////////////////////////////////////////////////
////// PVMFDownloadDataSourceContainer
////////////////////////////////////////////////////////////////////////////////////
// This container class wraps the data from all the download source data classes, i.e.,
// PVMFDownloadDataSourceHTTP, PVMFDownloadDataSourcePVX, PVMFSourceContextDataDownloadHTTP and PVMFSourceContextDataDownloadPVX
class CPVXInfo;
class PVMFDownloadDataSourceContainer
{
public:
bool iHasDataSource; // true means the constainer is already filled in the data source
bool iIsNewSession; // true if the downloading a new file, false if keep downloading a partial downloading file
uint32 iMaxFileSize; // the max size of the file.
uint32 iPlaybackControl; // correspond to PVMFDownloadDataSourceHTTP::TPVPlaybackControl, PVMFSourceContextDataDownloadHTTP::TPVPlaybackControl
OSCL_wHeapString<OsclMemAllocator> iConfigFileName; // download config file
OSCL_wHeapString<OsclMemAllocator> iDownloadFileName; // local file name of the downloaded clip
OSCL_HeapString<OsclMemAllocator> iProxyName; // HTTP proxy name, either ip or dns
uint32 iProxyPort; // HTTP proxy port
OSCL_HeapString<OsclMemAllocator> iUserID; // UserID string used for HTTP basic/digest authentication
OSCL_HeapString<OsclMemAllocator> iUserPasswd; // password string used for HTTP basic/digest authentication
CPVXInfo *iPvxInfo; // Fasttrack only, contains all the info in the .pvx file except the URL
public:
// default constructor
PVMFDownloadDataSourceContainer()
{
clear();
}
bool isEmpty()
{
return !iHasDataSource;
}
// major copy constructor to do type conversion
PVMFDownloadDataSourceContainer(OsclAny* aSourceData);
// add source data
bool addSource(OsclAny* aSourceData);
void clear()
{
iHasDataSource = false;
iIsNewSession = true;
iMaxFileSize = 0;
iPlaybackControl = 0;
iProxyPort = 0;
iPvxInfo = NULL;
}
private:
// type conversion routine for each download source data class
void copy(const PVMFDownloadDataSourceHTTP& aSourceData);
void copy(const PVMFDownloadDataSourcePVX& aSourceData);
void copy(const PVMFSourceContextDataDownloadHTTP& aSourceData);
void copy(const PVMFSourceContextDataDownloadPVX& aSourceData);
PVMFSourceContextDataDownloadHTTP::TPVPlaybackControl convert(const PVMFDownloadDataSourceHTTP::TPVPlaybackControl aPlaybackControl);
};
////////////////////////////////////////////////////////////////////////////////////
////// PVDlCfgFileContainer and its derived class definition
////////////////////////////////////////////////////////////////////////////////////
class PVDlCfgFileContainer
{
public:
virtual ~PVDlCfgFileContainer() {}
PVDlCfgFileContainer(PVMFDownloadDataSourceContainer *aDataSource) :
iPlaybackMode(PVMFDownloadDataSourceHTTP::EAsap),
iDataSource(aDataSource)
{
iDataPathLogger = PVLogger::GetLoggerObject("datapath.sourcenode.protocolenginenode");
}
virtual PVMFStatus createCfgFile(OSCL_String &aUrl);
void setDataSource(PVMFDownloadDataSourceContainer *aDataSource)
{
iDataSource = aDataSource;
}
// get API
OsclSharedPtr<PVDlCfgFile> &getCfgFile()
{
return iCfgFileObj;
}
PVMFDownloadDataSourceHTTP::TPVPlaybackControl getPlaybackMode()
{
return iPlaybackMode;
}
bool isEmpty()
{
return (iCfgFileObj.GetRep() == NULL);
}
virtual void saveConfig()
{
if (!isEmpty()) iCfgFileObj->SaveConfig();
}
protected:
virtual PVMFStatus configCfgFile(OSCL_String &aUrl);
PVMFStatus loadOldConfig(); // utility function for configCfgFile()
protected:
OsclSharedPtr<PVDlCfgFile> iCfgFileObj;
PVMFDownloadDataSourceHTTP::TPVPlaybackControl iPlaybackMode;
PVMFDownloadDataSourceContainer *iDataSource;
PVLogger* iDataPathLogger;
};
////////////////////////////////////////////////////////////////////////////////////
////// downloadEventReporter
////////////////////////////////////////////////////////////////////////////////////
class downloadEventReporter : public EventReporter
{
public:
// constructor
downloadEventReporter(PVMFProtocolEngineNode *aNode);
virtual bool checkReportEvent(const uint32 downloadStatus);
bool checkContentInfoEvent(const uint32 downloadStatus);
void clear();
// enable some specific events
void sendDataReadyEvent();
void enableBufferingCompleteEvent();
void sendBufferStatusEvent();
protected:
virtual bool needToCheckContentInfoEvent()
{
return true;
}
virtual void checkUnexpectedDataAndServerDisconnectEvent(const uint32 downloadStatus);
protected:
// supporting function for checkReportEvent()
bool checkBufferInfoEvent(const uint32 downloadStatus);
// check and send buffer complete, data ready and unexpected data events
void checkBufferCompleteEvent(const uint32 downloadStatus);
void checkUnexpectedDataEvent(const uint32 downloadStatus);
virtual void checkServerDisconnectEvent(const uint32 downloadStatus);
// for checkContentInfoEvent()
bool checkContentLengthOrTooLarge();
bool checkContentTruncated(const uint32 downloadStatus);
int32 isDownloadFileTruncated(const uint32 downloadStatus);
bool isDownloadComplete(const uint32 downloadStatus) const
{
return (downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE ||
downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_TRUNCATED ||
downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA ||
downloadStatus == PROCESS_SUCCESS_END_OF_MESSAGE_BY_SERVER_DISCONNECT);
}
// will be overriden in case of PS
// called by sendBufferStatusEventBody()
virtual void reportBufferStatusEvent(const uint32 aDownloadPercent);
protected:
bool iSendBufferStartInfoEvent;
bool iSendBufferCompleteInfoEvent;
bool iSendMovieAtomCompleteInfoEvent;
bool iSendInitialDataReadyEvent;
bool iSendContentLengthEvent;
bool iSendContentTruncateEvent;
bool iSendContentTypeEvent;
bool iSendUnexpectedDataEvent;
bool iSendServerDisconnectEvent;
private:
void sendBufferStatusEventBody(const bool aForceToSend = false);
private:
uint32 iPrevDownloadProgress;
};
#endif