Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #include "pvmf_protocol_engine_node.h"
     19 #include "pvmf_protocol_engine_node_progressive_download.h"
     20 #include "pvmf_protocolengine_node_tunables.h"
     21 #include "pvmf_protocol_engine_progressive_download.h"
     22 
     23 
     24 #define GET_10_PERCENT(x) ( ((x)>>3)-((x)>>6) ) // 1/8 - 1/64 = 0.109
     25 
     26 
     27 ////////////////////////////////////////////////////////////////////////////////////
     28 //////  ProgessiveDownloadContainer implementation
     29 ////////////////////////////////////////////////////////////////////////////////////
     30 OSCL_EXPORT_REF ProgressiveDownloadContainer::ProgressiveDownloadContainer(PVMFProtocolEngineNode *aNode) :
     31         DownloadContainer(aNode),
     32         iNumCheckExtraDataComeIn(0),
     33         iNumCheckEOSAfterDisconnectSocket(0)
     34 {
     35     ;
     36 }
     37 
     38 OSCL_EXPORT_REF bool ProgressiveDownloadContainer::createProtocolObjects()
     39 {
     40     if (!ProtocolContainer::createProtocolObjects()) return false;
     41 
     42     iProtocol         = OSCL_NEW(ProgressiveDownload, ());
     43     iNodeOutput       = OSCL_NEW(pvHttpDownloadOutput, (iNode));
     44     iDownloadControl  = OSCL_NEW(progressiveDownloadControl, ());
     45     iDownloadProgess  = OSCL_NEW(ProgressiveDownloadProgress, ());
     46     iEventReport      = OSCL_NEW(downloadEventReporter, (iNode));
     47     iCfgFileContainer = OSCL_NEW(PVProgressiveDownloadCfgFileContainer, (iDownloadSource));
     48     iUserAgentField   = OSCL_NEW(UserAgentFieldForProgDownload, ());
     49     iDownloadSource   = OSCL_NEW(PVMFDownloadDataSourceContainer, ());
     50 
     51     if (!iProtocol      || !iNodeOutput  || !iDownloadControl  ||
     52             !iDownloadProgess || !iEventReport || !iCfgFileContainer ||
     53             !iUserAgentField  || !iDownloadSource) return false;
     54 
     55     DownloadContainer::setEventReporterSupportObjects();
     56     return true;
     57 }
     58 
     59 OSCL_EXPORT_REF bool ProgressiveDownloadContainer::needSocketReconnect()
     60 {
     61     // currently, only disallow socket reconnect for head request disabled during prepare->start
     62     if (iObserver->GetObserverState() == (uint32)EPVMFNodePrepared &&
     63             iInterfacingObjectContainer->getHttpHeadRequestDisabled() &&
     64             !iForceSocketReconnect) return false;
     65     return true;
     66 }
     67 
     68 OSCL_EXPORT_REF PVMFStatus ProgressiveDownloadContainer::initImpl()
     69 {
     70     if (!iInterfacingObjectContainer->getHttpHeadRequestDisabled()) return ProtocolContainer::initImpl();
     71 
     72     if (!isObjectsReady())
     73     {
     74         return PVMFErrNotReady;
     75     }
     76 
     77     // initialize output object
     78     int32 status = initNodeOutput();
     79     if (status != PVMFSuccess) return status;
     80 
     81     // initialize protocol object
     82     if (!initProtocol()) return PVMFFailure;
     83 
     84     // initialize download control object
     85     initDownloadControl();
     86 
     87     return PVMFSuccess;
     88 }
     89 
     90 OSCL_EXPORT_REF bool ProgressiveDownloadContainer::initProtocol_SetConfigInfo()
     91 {
     92     OsclSharedPtr<PVDlCfgFile> aCfgFile = iCfgFileContainer->getCfgFile();
     93     if (aCfgFile.GetRep() == NULL) return false;
     94     aCfgFile->setHttpHeadRequestDisabled(iInterfacingObjectContainer->getHttpHeadRequestDisabled());
     95     return DownloadContainer::initProtocol_SetConfigInfo();
     96 }
     97 
     98 
     99 ////////////////////////////////////////////////////////////////////////////////////
    100 //////  progressiveDownloadControl implementation
    101 ////////////////////////////////////////////////////////////////////////////////////
    102 OSCL_EXPORT_REF bool progressiveDownloadControl::isDlAlgoPreConditionMet(const uint32 aDownloadRate,
    103         const uint32 aDurationMsec,
    104         const uint32 aCurrDownloadSize,
    105         const uint32 aFileSize)
    106 {
    107     // first make sure initial download pre-conditions should be met
    108     if (!pvDownloadControl::isDlAlgoPreConditionMet(aDownloadRate, aDurationMsec, aCurrDownloadSize, aFileSize)) return false;
    109 
    110     // then heck the parser consuming rate is close to clip bitrate
    111     int32 status = isPlaybackRateCloseToClipBitrate(aDurationMsec, aCurrDownloadSize, aFileSize);
    112     if (status == 0) return true;  // parser node data consumption rate is close to clip bitrate
    113     if (status == -1) return true; // duration is not available, then don't wait and kicks off algo running
    114 
    115     return false; // parser node data consumption rate is not close to clip bitrate
    116 }
    117 
    118 // ret_val: 0,  success,
    119 //          1,  playback rate is not close to clip bitrate, but the information is all available
    120 //          -1, related information, e.g. duration=0, size2time conversion is not available, is not available
    121 OSCL_EXPORT_REF int32 progressiveDownloadControl::isPlaybackRateCloseToClipBitrate(const uint32 aDurationMsec,
    122         const uint32 aCurrDownloadSize,
    123         const uint32 aFileSize)
    124 {
    125     if (aFileSize == 0 || aDurationMsec == 0 || iProgDownloadSI == NULL) return -1;
    126 
    127     uint32 aNPTInMS = 0;
    128 
    129     if (iProgDownloadSI->convertSizeToTime(aCurrDownloadSize, aNPTInMS) == 0)
    130     {
    131 
    132         if (aNPTInMS == 0) return 1;
    133         if (iClipByterate == 0) iClipByterate = divisionInMilliSec(aFileSize, aDurationMsec);   // aFileSize*1000/aDurationMsec
    134         uint32 aInstantByterate = divisionInMilliSec(aCurrDownloadSize, aNPTInMS);          // aCurrDownloadSize*1000/aNPTInMS
    135         LOGINFODATAPATH((0, "progressiveDownloadControl::isPlaybackRateCloseToClipBitrate, check Instant rate=%d(currDLSize=%d, NPTTimeMs=%d), clip bitrate=%d",
    136                          (aInstantByterate << 3), aCurrDownloadSize, aNPTInMS, (iClipByterate << 3)));
    137         uint32 diffByterate = (aInstantByterate >= iClipByterate ? aInstantByterate - iClipByterate : iClipByterate - aInstantByterate);
    138         if (diffByterate < GET_10_PERCENT(iClipByterate) || // OSCL_ABS(aInstantByterate-iClipByterate)/iClipByterate < 1/8-1/64=0.109
    139                 isBufferingEnoughTime(aCurrDownloadSize, PVPROTOCOLENGINE_JITTER_BUFFER_SIZE_TIME, aNPTInMS))
    140         {
    141             if (isBufferingEnoughTime(aCurrDownloadSize, PVPROTOCOLENGINE_JITTER_BUFFER_SIZE_TIME, aNPTInMS))
    142             {
    143                 return 0;
    144             }
    145             return 1;
    146         }
    147     }
    148     else
    149     {
    150         // in case of convertSizeToTime() not supported in parser node, but duration can be estimated and provided
    151         if (iClipByterate == 0) iClipByterate = divisionInMilliSec(aFileSize, aDurationMsec);
    152         if (isBufferingEnoughTime(aCurrDownloadSize, PVPROTOCOLENGINE_INIT_DOWNLOAD_TIME_THRESHOLD_WITH_CLIPBITRATE)) return 0;
    153     }
    154 
    155     return 1;
    156 }
    157 
    158 OSCL_EXPORT_REF bool progressiveDownloadControl::isBufferingEnoughTime(const uint32 aCurrDownloadSize,
    159         const uint32 aBufferTimeLimitInSec,
    160         const uint32 aNPTInMS)
    161 {
    162     if (aNPTInMS == 0xFFFFFFFF)
    163     {
    164         // use clip bitrate to calculate buffering time, instead of using convertSizeToTime()
    165         uint32 deltaSizeLimit = iClipByterate * aBufferTimeLimitInSec;
    166         return (aCurrDownloadSize >= iPrevDownloadSize + deltaSizeLimit);
    167     }
    168     else if (aNPTInMS > 0)
    169     {
    170         // convertSizeToTime() should be available
    171         if (iPrevDownloadSize == 0)
    172         {
    173             return (aNPTInMS >= aBufferTimeLimitInSec*1000);
    174         }
    175         else
    176         {
    177             uint32 aPrevNPTInMS = 0;
    178             if (iProgDownloadSI->convertSizeToTime(iPrevDownloadSize, aPrevNPTInMS) == 0)
    179             {
    180                 return (aNPTInMS > aPrevNPTInMS && (aNPTInMS - aPrevNPTInMS) >= aBufferTimeLimitInSec*1000);
    181             }
    182         }
    183     }
    184     return false;
    185 }
    186 
    187 OSCL_EXPORT_REF bool progressiveDownloadControl::checkNewDuration(const uint32 aCurrDurationMsec, uint32 &aNewDurationMsec)
    188 {
    189     aNewDurationMsec = aCurrDurationMsec;
    190     if (aCurrDurationMsec > 0 && iClipByterate == 0)
    191     {
    192         if (iFileSize > 0) iClipByterate = divisionInMilliSec(iFileSize, aCurrDurationMsec);
    193     }
    194 
    195     if (iPlaybackByteRate > 0)
    196     {
    197         if (iPlaybackByteRate > iClipByterate)
    198         {
    199             uint32 averPlaybackRate = (iClipByterate + iPlaybackByteRate) / 2;
    200             aNewDurationMsec = divisionInMilliSec(iFileSize, averPlaybackRate); // aFileSize/averPlaybackRate*1000
    201         }
    202     }
    203     return true;
    204 }
    205 
    206 OSCL_EXPORT_REF bool progressiveDownloadControl::approveAutoResumeDecisionShortCut(const uint32 aCurrDownloadSize,
    207         const uint32 aDurationMsec,
    208         const uint32 aPlaybackTimeMsec,
    209         uint32 &aPlaybackRemainingTimeMsec)
    210 {
    211     if (!iProgDownloadSI || aDurationMsec == 0) return false;
    212 
    213     uint32 aNPTInMS = 0;
    214     if (iProgDownloadSI->convertSizeToTime(aCurrDownloadSize, aNPTInMS) == 0)
    215     {
    216         aPlaybackRemainingTimeMsec = aDurationMsec - aNPTInMS;
    217         if (aNPTInMS > PVPROTOCOLENGINE_JITTER_BUFFER_SIZE_TIME*2000 + aPlaybackTimeMsec)
    218             return true;
    219     }
    220     return false;
    221 }
    222 
    223 // No constraint: for file size/clip duration/clip bitrate(i.e. playback rate), one of them must be unavailable, except
    224 // file size and clip duration are available, but clip bitrate is unavailable
    225 OSCL_EXPORT_REF bool progressiveDownloadControl::checkAutoResumeAlgoNoConstraint(const uint32 aCurrDownloadSize,
    226         const uint32 aFileSize,
    227         uint32 &aDurationMsec)
    228 {
    229     // first check one exception: file size>0, duration=0, playbackRate>0, then we need to estimate the clip duration
    230     if (checkEstDurationAvailable(aFileSize, aDurationMsec)) return false;
    231 
    232     uint32 currDownloadSizeOfInterest = aCurrDownloadSize - iPrevDownloadSize; // use download size as the jitter buffer size
    233     if (iPlaybackByteRate > 0) currDownloadSizeOfInterest /= iPlaybackByteRate; // use playback time as the jitter buffer size
    234     else if (aFileSize > 0) currDownloadSizeOfInterest /= (aFileSize / PVPROTOCOLENGINE_DOWNLOAD_BYTE_PERCENTAGE_CONVERTION_100); // use download percentage as the jitter buffer size
    235 
    236     uint32 aJitterBufferSize = (iPlaybackByteRate > 0 ? PVPROTOCOLENGINE_JITTER_BUFFER_SIZE_TIME :
    237                                 (aFileSize > 0 ? PVPROTOCOLENGINE_JITTER_BUFFER_SIZE_DLPERCENTAGE :
    238                                  PVPROTOCOLENGINE_JITTER_BUFFER_SIZE_BYTES));
    239     bool resumeOK = (currDownloadSizeOfInterest >= aJitterBufferSize);
    240     LOGINFODATAPATH((0, "progressiveDownloadControl::isResumePlayback()->checkAutoResumeAlgoNoConstraint(), resumeOK=%d, currDownloadSize=%d, prevDownloadSize=%d, currDownloadSizeOfInterest=%d, aJitterBufferSize=%d, file size=%d",
    241                      (uint32)resumeOK, aCurrDownloadSize, iPrevDownloadSize, currDownloadSizeOfInterest, aJitterBufferSize, aFileSize));
    242 
    243     return resumeOK;
    244 }
    245 
    246 OSCL_EXPORT_REF bool progressiveDownloadControl::checkEstDurationAvailable(const uint32 aFileSize, uint32 &aDurationMsec)
    247 {
    248     // check file size>0, duration=0, playbackRate>0, then we need to estimate the clip duration
    249     // and use the original algorithm
    250     if (iPlaybackByteRate > 0 && aFileSize > 0 && aDurationMsec == 0)
    251     {
    252         // calculate estimated duration
    253         aDurationMsec = divisionInMilliSec(aFileSize, iPlaybackByteRate);
    254         LOGINFODATAPATH((0, "progressiveDownloadControl::isResumePlayback()->checkEstDurationAvailable(), aFileSize=%d, aPlaybackByteRate=%d, estDurationMsec=%d",
    255                          aFileSize, iPlaybackByteRate, aDurationMsec));
    256         return true;
    257     }
    258     return false;
    259 }
    260 
    261 
    262 OSCL_EXPORT_REF bool progressiveDownloadControl::updateDownloadClock()
    263 {
    264     if (!iProgDownloadSI || !iProtocol) return false;
    265 
    266     // using size2time conversion to update download clock in PDL only applies to the case where
    267     // old algorithm gets running without engine clock input
    268     if (!iCurrentPlaybackClock)
    269     {
    270         uint32 aDownloadNPTTime = 0;
    271         // get download size from output object instead of protocol engine.
    272         // The download size from output object is the actual size for the data written to the file, and is exposed to user,
    273         // while the download size time from protocol engine is internally counted from socket and most likely
    274         // larger than that from output object
    275 
    276         if (iProgDownloadSI->convertSizeToTime(iNodeOutput->getCurrentOutputSize(), aDownloadNPTTime) != 0) return false;
    277         bool bOverflowFlag = false;
    278         iDlProgressClock->SetStartTime32(aDownloadNPTTime, PVMF_MEDIA_CLOCK_MSEC, bOverflowFlag);
    279     }
    280     return true;
    281 }
    282 
    283 
    284 ////////////////////////////////////////////////////////////////////////////////////
    285 //////  ProgressiveDownloadProgress implementation
    286 ////////////////////////////////////////////////////////////////////////////////////
    287 OSCL_EXPORT_REF void ProgressiveDownloadProgress::setSupportObject(OsclAny *aDLSupportObject, DownloadControlSupportObjectType aType)
    288 {
    289     switch (aType)
    290     {
    291         case DownloadControlSupportObjectType_ConfigFileContainer:
    292             iCfgFileContainer = (PVDlCfgFileContainer *)aDLSupportObject;
    293             break;
    294 
    295         case DownloadControlSupportObjectType_SupportInterface:
    296             iProgDownloadSI = (PVMFFormatProgDownloadSupportInterface*)aDLSupportObject;
    297             break;
    298 
    299         default:
    300             break;
    301     }
    302 
    303     DownloadProgress::setSupportObject(aDLSupportObject, aType);
    304 }
    305 
    306 OSCL_EXPORT_REF bool ProgressiveDownloadProgress::updateDownloadClock(const bool aDownloadComplete)
    307 {
    308     OSCL_UNUSED_ARG(aDownloadComplete);
    309     if (iProtocol) iDownloadSize = iNodeOutput->getCurrentOutputSize();
    310     if (iDownloadSize == 0) return false;
    311     return checkDownloadPercentModeAndUpdateDLClock();
    312 }
    313 
    314 OSCL_EXPORT_REF bool ProgressiveDownloadProgress::checkDownloadPercentModeAndUpdateDLClock()
    315 {
    316     // (1) if user specifies byte-based download percentage or no content length case,
    317     // no need to update download clock and download time
    318     if (iDownloadProgressMode > 0 ||
    319             iProtocol->getContentLength() == 0)
    320     {
    321         iTimeBasedDownloadPercent = false;
    322         return true;
    323     }
    324 
    325     // (2) if download and playback mode is not asap mode, i.e. download and play or download only,
    326     // then use byte-based download percent
    327     if (!iProgDownloadSI && iCfgFileContainer)
    328     {
    329         if (iCfgFileContainer->getPlaybackMode() != PVMFDownloadDataSourceHTTP::EAsap) iTimeBasedDownloadPercent = false;
    330         return true;
    331     }
    332 
    333     // (3) if parser node is not ready to do conversion from size to time,
    334     // then choose byte-based download percent
    335     if (iProgDownloadSI->convertSizeToTime(iDownloadSize, iDownloadNPTTime) != 0)
    336     {
    337         iTimeBasedDownloadPercent = false;
    338         return true;
    339     }
    340     return true;
    341 }
    342 
    343 OSCL_EXPORT_REF bool ProgressiveDownloadProgress::calculateDownloadPercent(uint32 &aDownloadProgressPercent)
    344 {
    345     return calculateDownloadPercentBody(aDownloadProgressPercent, iProtocol->getContentLength());
    346 }
    347 
    348 OSCL_EXPORT_REF bool ProgressiveDownloadProgress::calculateDownloadPercentBody(uint32 &aDownloadProgressPercent, const uint32 aFileSize)
    349 {
    350     if (iTimeBasedDownloadPercent)
    351     {
    352         return DownloadProgress::calculateDownloadPercent(aDownloadProgressPercent);
    353     }
    354     else
    355     {
    356         // byte-based download percentage
    357         aDownloadProgressPercent = iDownloadSize;
    358         if (aFileSize > 0)
    359         {
    360             aDownloadProgressPercent = getDownloadBytePercent(iDownloadSize, aFileSize);
    361             if (aDownloadProgressPercent > 100) aDownloadProgressPercent = 100;
    362             if (aDownloadProgressPercent == 100) iDownloadSize = aFileSize;
    363         }
    364         else
    365         {
    366             uint32 aMaxFileSize = iCfgFileContainer->getCfgFile()->GetMaxAllowedFileSize();
    367             if (aDownloadProgressPercent > aMaxFileSize) aDownloadProgressPercent = aMaxFileSize;
    368         }
    369     }
    370     return true;
    371 }
    372 
    373 // handle overflow issue for integer multiplication: downloadSize*100/fileSize
    374 OSCL_EXPORT_REF uint32 ProgressiveDownloadProgress::getDownloadBytePercent(const uint32 aDownloadSize, const uint32 aFileSize)
    375 {
    376     uint32 aDownloadProgressPercent = aDownloadSize * PVPROTOCOLENGINE_DOWNLOAD_BYTE_PERCENTAGE_CONVERTION_100 / aFileSize; // 100
    377     if ((aDownloadSize >> PVPROTOCOLENGINE_DOWNLOAD_BYTE_PERCENTAGE_DLSIZE_LIMIT_RIGHT_SHIFT_FACTOR) > 0)   // right shift 25 bits => larger than 2^25, then *100 may cause overflow
    378     {
    379         aDownloadProgressPercent = (aDownloadSize >> PVPROTOCOLENGINE_DOWNLOAD_BYTE_PERCENTAGE_DLSIZE_RIGHTSHIFT_FACTOR)* // right shift 7 bits, 2^7>100 to avoid overflow
    380                                    PVPROTOCOLENGINE_DOWNLOAD_BYTE_PERCENTAGE_CONVERTION_100 /
    381                                    (aFileSize >> PVPROTOCOLENGINE_DOWNLOAD_BYTE_PERCENTAGE_DLSIZE_RIGHTSHIFT_FACTOR);
    382     }
    383     return aDownloadProgressPercent;
    384 }
    385 
    386 OSCL_EXPORT_REF void ProgressiveDownloadProgress::reset()
    387 {
    388     DownloadProgress::reset();
    389 
    390     iCfgFileContainer = NULL;
    391     iProgDownloadSI   = NULL;
    392     iTimeBasedDownloadPercent = false;
    393     iDownloadProgressMode = (uint32)DownloadProgressMode_ByteBased;
    394 }
    395 
    396 ////////////////////////////////////////////////////////////////////////////////////
    397 //////  UserAgentField implementation
    398 ////////////////////////////////////////////////////////////////////////////////////
    399 OSCL_EXPORT_REF UserAgentFieldForProgDownload::UserAgentFieldForProgDownload(OSCL_wString &aUserAgent, const bool isOverwritable) :
    400         UserAgentField(aUserAgent, isOverwritable)
    401 {
    402     ;
    403 }
    404 
    405 OSCL_EXPORT_REF UserAgentFieldForProgDownload::UserAgentFieldForProgDownload(OSCL_String &aUserAgent, const bool isOverwritable) :
    406         UserAgentField(aUserAgent, isOverwritable)
    407 {
    408     ;
    409 }
    410 
    411 OSCL_EXPORT_REF void UserAgentFieldForProgDownload::getDefaultUserAgent(OSCL_String &aUserAgent)
    412 {
    413     OSCL_HeapString<OsclMemAllocator> defaultUserAgent(PDL_HTTP_USER_AGENT); // defined in pvmf_protocolengine_node_tunables.h
    414     aUserAgent = defaultUserAgent;
    415 }
    416 
    417 
    418 ////////////////////////////////////////////////////////////////////////////////////
    419 //////  PVProgressiveDownloadCfgFileContainer implementation
    420 ////////////////////////////////////////////////////////////////////////////////////
    421 
    422 OSCL_EXPORT_REF PVMFStatus PVProgressiveDownloadCfgFileContainer::configCfgFile(OSCL_String &aUrl)
    423 {
    424     // playback mode and proxy
    425     iPlaybackMode = (PVMFDownloadDataSourceHTTP::TPVPlaybackControl)iDataSource->iPlaybackControl;
    426     iCfgFileObj->SetPlaybackMode(convertToConfigFilePlaybackMode(iPlaybackMode));
    427     iCfgFileObj->SetProxyName(iDataSource->iProxyName);
    428     iCfgFileObj->SetProxyPort(iDataSource->iProxyPort);
    429 
    430     // user agent
    431     OSCL_FastString user_agent(PDL_HTTP_USER_AGENT); // defined in pvmf_protocolengine_node_tunables.h
    432     iCfgFileObj->SetUserAgent(user_agent);
    433 
    434     // user-id and password
    435     if (iDataSource->iUserID.get_size() > 0)      iCfgFileObj->SetUserId(iDataSource->iUserID);
    436     if (iDataSource->iUserPasswd.get_size() > 0) iCfgFileObj->SetUserAuth(iDataSource->iUserPasswd);
    437 
    438     iCfgFileObj->SetDownloadType(false);//not fasttrack
    439     return PVDlCfgFileContainer::configCfgFile(aUrl);
    440 }
    441 
    442 OSCL_EXPORT_REF PVDlCfgFile::TPVDLPlaybackMode PVProgressiveDownloadCfgFileContainer::convertToConfigFilePlaybackMode(PVMFDownloadDataSourceHTTP::TPVPlaybackControl aPlaybackMode)
    443 {
    444     OSCL_UNUSED_ARG(aPlaybackMode);
    445 
    446     PVDlCfgFile::TPVDLPlaybackMode mode = PVDlCfgFile::EPVDL_ASAP;
    447     switch (iPlaybackMode)
    448     {
    449         case PVMFDownloadDataSourceHTTP::EAsap:
    450             mode = PVDlCfgFile::EPVDL_ASAP;
    451             break;
    452         case PVMFDownloadDataSourceHTTP::EAfterDownload:
    453             mode = PVDlCfgFile::EPVDL_PLAYBACK_AFTER_DOWNLOAD;
    454             break;
    455         case PVMFDownloadDataSourceHTTP::ENoPlayback:
    456             mode = PVDlCfgFile::EPVDL_DOWNLOAD_ONLY;
    457             break;
    458         default:
    459             break;
    460     }
    461     return mode;
    462 }
    463 
    464