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 "pvmi_media_io_fileoutput.h"
     19 #include "pvlogger.h"
     20 #include "pv_mime_string_utils.h"
     21 #include "oscl_snprintf.h"
     22 #include "pvmf_timedtext.h"
     23 #include "oscl_file_io.h"
     24 
     25 #include "oscl_dll.h"
     26 
     27 #include "pvmf_video.h"
     28 #include "pvmf_common_audio_decnode.h"
     29 
     30 #define LOG_OUTPUT_TO_FILE  1
     31 
     32 // Define entry point for this DLL
     33 OSCL_DLL_ENTRY_POINT_DEFAULT()
     34 
     35 //The factory functions.
     36 #include "pvmi_media_io_fileoutput_registry_factory.h"
     37 #include "oscl_mem.h"
     38 
     39 #define QUEUE_LIMIT 10
     40 
     41 OSCL_EXPORT_REF PvmiMIOControl* PVMFMediaFileOutputRegistryFactory::CreateMediaIO(OsclAny* aParam)
     42 {
     43     PVRefFileOutput* ptr = OSCL_NEW
     44 
     45                            (PVRefFileOutput, ((oscl_wchar*)aParam));
     46     return ptr;
     47 }
     48 
     49 OSCL_EXPORT_REF void PVMFMediaFileOutputRegistryFactory::ReleaseMediaIO(PvmiMIOControl* aNode)
     50 {
     51     OSCL_DELETE(aNode);
     52 }
     53 
     54 // This class implements the reference media IO for file output
     55 // This class constitutes the Media IO component
     56 
     57 
     58 OSCL_EXPORT_REF PVRefFileOutput::PVRefFileOutput(const OSCL_wString& aFileName, bool logStrings)
     59         : OsclTimerObject(OsclActiveObject::EPriorityNominal, "pvreffileoutput")
     60         , iOutputFileName(aFileName)
     61 #if (LOG_OUTPUT_TO_FILE)
     62         , iLogOutputToFile(true)
     63 #else
     64         , iLogOutputToFile(false)
     65 #endif
     66 {
     67     initData();
     68     iLogStrings = logStrings;
     69     iMediaType = MEDIATYPE_UNKNOWN;
     70 }
     71 
     72 
     73 OSCL_EXPORT_REF PVRefFileOutput::PVRefFileOutput(const OSCL_wString& aFileName
     74         , PVRefFileOutputTestObserver*aTestObs
     75         , bool aSimTiming, uint32 aQueueLimit
     76         , bool aSimFlowControl
     77         , bool logStrings)
     78         : OsclTimerObject(OsclActiveObject::EPriorityNominal, "pvreffileoutput")
     79         , iOutputFileName(aFileName)
     80 #if (LOG_OUTPUT_TO_FILE)
     81         , iLogOutputToFile(true)
     82 #else
     83         , iLogOutputToFile(false)
     84 #endif
     85 {
     86     initData();
     87     //test features...
     88     iSimFlowControl = aSimFlowControl;
     89     iTestObserver = aTestObs;
     90     iActiveTiming = NULL;
     91     iMediaType = MEDIATYPE_UNKNOWN;
     92     if (aSimTiming)
     93     {
     94         OsclMemAllocator alloc;
     95         OsclAny*ptr = alloc.allocate(sizeof(PVRefFileOutputActiveTimingSupport));
     96         if (ptr)
     97         {
     98             iActiveTiming = OSCL_PLACEMENT_NEW(ptr, PVRefFileOutputActiveTimingSupport(aQueueLimit));
     99         }
    100         // For active MIO assuming it to be audio MIO.
    101         iMediaType = MEDIATYPE_AUDIO;
    102     }
    103     iLogStrings = logStrings;
    104     iParametersLogged = false;
    105 }
    106 
    107 OSCL_EXPORT_REF PVRefFileOutput::PVRefFileOutput(const oscl_wchar* aFileName
    108         , bool aActiveTiming)
    109         : OsclTimerObject(OsclActiveObject::EPriorityNominal, "pvreffileoutput")
    110         , iOutputFileName(aFileName)
    111 #if (LOG_OUTPUT_TO_FILE)
    112         , iLogOutputToFile(true)
    113 #else
    114         , iLogOutputToFile(false)
    115 #endif
    116 {
    117     initData();
    118     iActiveTiming = NULL;
    119     iMediaType = MEDIATYPE_UNKNOWN;
    120     if (aActiveTiming)
    121     {
    122         OsclMemAllocator alloc;
    123         OsclAny*ptr = alloc.allocate(sizeof(PVRefFileOutputActiveTimingSupport));
    124         if (ptr)
    125         {
    126             iActiveTiming = OSCL_PLACEMENT_NEW(ptr, PVRefFileOutputActiveTimingSupport(QUEUE_LIMIT));
    127         }
    128         // For active MIO assuming it to be audio MIO.
    129         iMediaType = MEDIATYPE_AUDIO;
    130     }
    131 }
    132 
    133 OSCL_EXPORT_REF PVRefFileOutput::PVRefFileOutput(const oscl_wchar* aFileName,
    134         MediaType aMediaType,
    135         bool aCompressedMedia)
    136         : OsclTimerObject(OsclActiveObject::EPriorityNominal, "pvreffileoutput")
    137         , iOutputFileName(aFileName)
    138         , iMediaType(aMediaType)
    139         , iCompressedMedia(aCompressedMedia)
    140 #if (LOG_OUTPUT_TO_FILE)
    141         , iLogOutputToFile(true)
    142 #else
    143         , iLogOutputToFile(false)
    144 #endif
    145 {
    146     initData();
    147 }
    148 
    149 void PVRefFileOutput::initData()
    150 {
    151     iAudioFormat = PVMF_MIME_FORMAT_UNKNOWN;
    152     iAudioNumChannelsValid = false;
    153     iAudioSamplingRateValid = false;
    154 
    155     iVideoFormat = PVMF_MIME_FORMAT_UNKNOWN;
    156     iVideoHeightValid = false;
    157     iVideoWidthValid = false;
    158     iVideoDisplayHeightValid = false;
    159     iVideoDisplayWidthValid = false;
    160 
    161     iCommandCounter = 0;
    162     iLogger = NULL;
    163     iFileOpened = false;
    164     iFsConnected = false;
    165     iCommandResponseQueue.reserve(5);
    166     iWriteResponseQueue.reserve(5);
    167     iObserver = NULL;
    168     iLogger = NULL;
    169     iPeer = NULL;
    170     iState = STATE_IDLE;
    171     iWriteBusy = false;
    172     iWriteBusySeqNum = 0;
    173 
    174     //test features...
    175     iSimFlowControl = false;
    176     iTestObserver = NULL;
    177     iActiveTiming = NULL;
    178     iLogStrings = false;
    179     iParametersLogged = false;
    180     iFormatMask = 0;
    181     iTextFormat = PVMF_MIME_FORMAT_UNKNOWN;
    182     iUseClockExtension = false;
    183     iRIFFChunk.chunkID = FOURCC_RIFF;//0x46464952;   //"RIFF" in ASCII form, big-endian form
    184     iRIFFChunk.chunkSize = 0;
    185     iRIFFChunk.format  = FOURCC_WAVE;//0x45564157;   //"WAVE" in ASCII form, big-endian form
    186 
    187     iFmtSubchunk.subchunk1ID = FOURCC_fmt;//0x20746d66;   //"fmt " in ASCII form, big-endian form
    188     iFmtSubchunk.subchunk1Size = 16;         //for PCM16
    189     iFmtSubchunk.audioFormat   = 1;          //PCM = 1
    190     iFmtSubchunk.numChannels   = 0;
    191     iFmtSubchunk.sampleRate    = 0;
    192     iFmtSubchunk.byteRate      = 0;
    193     iFmtSubchunk.blockAlign    = 0;
    194     iFmtSubchunk.bitsPerSample = 16;
    195 
    196     iDataSubchunk.subchunk2ID  = FOURCC_data;//0x61746164;  //"data" in ASCII form, big-endian form
    197     iDataSubchunk.subchunk2Size = 0;
    198 
    199     iHeaderWritten = false;
    200     iAudioFormat = 0;
    201     iVideoFormat = 0;
    202     iInitializeAVIDone = false;
    203     iAVIChunkSize = 0;
    204     iVideoLastTimeStamp = 0;
    205     iVideoCount = 0;
    206     iIsMIOConfigured = false;
    207     iClock = NULL;
    208     //Connect with file server.
    209     if (!iFsConnected)
    210     {
    211         if (iFs.Connect() == 0)
    212         {
    213             iFsConnected = true;
    214         }
    215         else
    216         {
    217             OSCL_ASSERT(false);
    218         }
    219     }
    220 }
    221 
    222 void PVRefFileOutput::setUserClockExtnInterface(bool aEnable)
    223 {
    224     if (aEnable == true)
    225     {
    226         iUseClockExtension = true;
    227     }
    228     else
    229     {
    230         iUseClockExtension = false;
    231     }
    232 
    233 }
    234 
    235 void PVRefFileOutput::ResetData()
    236 //reset all data from this session.
    237 {
    238     if (iAudioFormat == PVMF_MIME_PCM16 || iAudioFormat == PVMF_MIME_PCM8)
    239     {
    240         UpdateWaveChunkSize();
    241     }
    242 
    243     if (iVideoFormat == PVMF_MIME_YUV420)
    244     {
    245         UpdateVideoChunkHeaderIdx();
    246     }
    247     Cleanup();
    248 
    249     //reset all the received media parameters.
    250 
    251     iAudioFormatString = "";
    252     iAudioFormat = PVMF_MIME_FORMAT_UNKNOWN;
    253     iAudioNumChannelsValid = false;
    254     iAudioSamplingRateValid = false;
    255 
    256     iVideoFormatString = "";
    257     iVideoFormat = PVMF_MIME_FORMAT_UNKNOWN;
    258     iVideoHeightValid = false;
    259     iVideoWidthValid = false;
    260     iVideoDisplayHeightValid = false;
    261     iVideoDisplayWidthValid = false;
    262     iIsMIOConfigured = false;
    263 
    264     iTextFormatString = "";
    265     iTextFormat = PVMF_MIME_FORMAT_UNKNOWN;
    266 
    267     iParametersLogged = false;
    268 }
    269 
    270 void PVRefFileOutput::Cleanup()
    271 //cleanup all allocated memory and release resources.
    272 {
    273     if (iFileOpened)
    274     {
    275         iOutputFile.Flush();
    276         iOutputFile.Close();
    277     }
    278     iFileOpened = false;
    279 
    280     while (!iCommandResponseQueue.empty())
    281     {
    282         if (iObserver)
    283         {
    284             iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus));
    285         }
    286         iCommandResponseQueue.erase(&iCommandResponseQueue[0]);
    287     }
    288     while (!iWriteResponseQueue.empty())
    289     {
    290         if (iPeer)
    291         {
    292             iPeer->writeComplete(iWriteResponseQueue[0].iStatus, iWriteResponseQueue[0].iCmdId, (OsclAny*)iWriteResponseQueue[0].iContext);
    293         }
    294         iWriteResponseQueue.erase(&iWriteResponseQueue[0]);
    295     }
    296 }
    297 
    298 PVRefFileOutput::~PVRefFileOutput()
    299 {
    300     Cleanup();
    301 
    302     if (iActiveTiming)
    303     {
    304         iActiveTiming->~PVRefFileOutputActiveTimingSupport();
    305         OsclMemAllocator alloc;
    306         alloc.deallocate(iActiveTiming);
    307         iActiveTiming = NULL;
    308     }
    309 
    310     if (iFsConnected)
    311     {
    312         iFs.Close();
    313     }
    314     iFsConnected = false;
    315 }
    316 
    317 
    318 PVMFStatus PVRefFileOutput::connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver)
    319 {
    320     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::connect() called"));
    321     // Each Session could have its own set of Comfiguration parametres
    322     //in an array of structures and the session ID could be an index to that array.
    323 
    324     OSCL_UNUSED_ARG(aSession);
    325     //currently supports only one session
    326     if (iObserver)
    327     {
    328         return PVMFFailure;
    329     }
    330 
    331     iObserver = aObserver;
    332     return PVMFSuccess;
    333 }
    334 
    335 
    336 PVMFStatus PVRefFileOutput::disconnect(PvmiMIOSession aSession)
    337 {
    338     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::disconnect() called"));
    339     OSCL_UNUSED_ARG(aSession);
    340 
    341     // just set the observer to NULL, any command completes should be done before disconnect.
    342     iObserver = NULL;
    343     return PVMFSuccess;
    344 }
    345 
    346 
    347 PvmiMediaTransfer* PVRefFileOutput::createMediaTransfer(PvmiMIOSession& aSession,
    348         PvmiKvp* read_formats, int32 read_flags,
    349         PvmiKvp* write_formats, int32 write_flags)
    350 {
    351     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::createMediaTransfer() called"));
    352 
    353     OSCL_UNUSED_ARG(aSession);
    354     OSCL_UNUSED_ARG(read_formats);
    355     OSCL_UNUSED_ARG(read_flags);
    356     OSCL_UNUSED_ARG(write_formats);
    357     OSCL_UNUSED_ARG(write_flags);
    358 
    359     return (PvmiMediaTransfer*)this;
    360 }
    361 
    362 void PVRefFileOutput::QueueCommandResponse(CommandResponse& aResp)
    363 {
    364     //queue a command response and schedule processing.
    365 
    366     iCommandResponseQueue.push_back(aResp);
    367 
    368     //cancel any timer delay so the command response will happen ASAP.
    369     if (IsBusy())
    370     {
    371         Cancel();
    372     }
    373 
    374     RunIfNotReady();
    375 }
    376 
    377 PVMFCommandId PVRefFileOutput::QueryUUID(const PvmfMimeString& aMimeType,
    378         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    379         bool aExactUuidsOnly, const OsclAny* aContext)
    380 {
    381     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::QueryUUID() called"));
    382 
    383     OSCL_UNUSED_ARG(aMimeType);
    384     OSCL_UNUSED_ARG(aExactUuidsOnly);
    385 
    386     PVMFCommandId cmdid = iCommandCounter++;
    387 
    388     PVMFStatus status = PVMFFailure;
    389     int32 err ;
    390     OSCL_TRY(err,
    391              aUuids.push_back(PVMI_CAPABILITY_AND_CONFIG_PVUUID);
    392              if (iActiveTiming)
    393 {
    394     PVUuid uuid;
    395     iActiveTiming->queryUuid(uuid);
    396         aUuids.push_back(uuid);
    397     }
    398             );
    399     if (err == OsclErrNone)
    400     {
    401         status = PVMFSuccess;
    402     }
    403 
    404     CommandResponse resp(status, cmdid, aContext);
    405     QueueCommandResponse(resp);
    406     return cmdid;
    407 }
    408 
    409 
    410 PVMFCommandId PVRefFileOutput::QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext)
    411 {
    412     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::QueryInterface() called"));
    413 
    414     PVMFCommandId cmdid = iCommandCounter++;
    415 
    416     PVMFStatus status = PVMFFailure;
    417     if (aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
    418     {
    419         PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
    420         aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface);
    421         status = PVMFSuccess;
    422     }
    423     else if (aUuid == PvmiClockExtensionInterfaceUuid)
    424     {
    425         //the clock extension interface is present only when the component
    426         //has active timing.
    427         if (iActiveTiming)
    428         {
    429             PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, iActiveTiming);
    430             aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface);
    431             status = PVMFSuccess;
    432         }
    433         else if (iUseClockExtension == true)
    434         {
    435             PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, this);
    436             aInterfacePtr = OSCL_STATIC_CAST(PVInterface*, myInterface);
    437             status = PVMFSuccess;
    438         }
    439         else
    440         {
    441             status = PVMFFailure;
    442         }
    443     }
    444     else
    445     {
    446         status = PVMFFailure;
    447     }
    448 
    449     CommandResponse resp(status, cmdid, aContext);
    450     QueueCommandResponse(resp);
    451     return cmdid;
    452 }
    453 
    454 
    455 void PVRefFileOutput::deleteMediaTransfer(PvmiMIOSession& aSession, PvmiMediaTransfer* media_transfer)
    456 {
    457     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::deleteMediaTransfer() called"));
    458     OSCL_UNUSED_ARG(aSession);
    459     OSCL_UNUSED_ARG(media_transfer);
    460 
    461     if (iWriteResponseQueue.empty() == false)
    462     {
    463         // All media transfer requests are not completed yet. Do a leave
    464         OSCL_LEAVE(OsclErrBusy);
    465         // return;  This statement was removed to avoid compiler warning for Unreachable Code
    466     }
    467 
    468     if (iPeer)
    469     {
    470         // Since media transfer is gone, peer is gone as well
    471         iPeer = NULL;
    472     }
    473 }
    474 
    475 
    476 PVMFCommandId PVRefFileOutput:: Init(const OsclAny* aContext)
    477 {
    478     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::Init() called"));
    479 
    480     PVMFCommandId cmdid = iCommandCounter++;
    481 
    482     PVMFStatus status = PVMFFailure;
    483 
    484     switch (iState)
    485     {
    486         case STATE_LOGGED_ON:
    487             if (!iFileOpened)
    488             {
    489                 if (iOutputFile.Open(iOutputFileName.get_cstr(), Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY, iFs) != 0)
    490                 {
    491                     status = PVMFFailure;
    492                 }
    493                 else
    494                 {
    495                     status = PVMFSuccess;
    496                     iFileOpened = true;
    497                 }
    498             }
    499             else
    500             {
    501                 status = PVMFSuccess;
    502                 iFileOpened = true;
    503             }
    504             if (status == PVMFSuccess)
    505             {
    506                 iState = STATE_INITIALIZED;
    507             }
    508             break;
    509 
    510         default:
    511             status = PVMFErrInvalidState;
    512             break;
    513     }
    514 
    515     CommandResponse resp(status, cmdid, aContext);
    516     QueueCommandResponse(resp);
    517     return cmdid;
    518 }
    519 
    520 PVMFCommandId PVRefFileOutput::Reset(const OsclAny* aContext)
    521 {
    522     // Reset all data from this session
    523     ResetData();
    524 
    525     // TEMP to properly behave asynchronously
    526     PVMFCommandId cmdid = iCommandCounter++;
    527     CommandResponse resp(PVMFSuccess, cmdid, aContext);
    528     QueueCommandResponse(resp);
    529     return cmdid;
    530 }
    531 
    532 PVMFCommandId PVRefFileOutput::Start(const OsclAny* aContext)
    533 {
    534     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::Start() called"));
    535 
    536     PVMFCommandId cmdid = iCommandCounter++;
    537 
    538     PVMFStatus status = PVMFFailure;
    539 
    540     switch (iState)
    541     {
    542         case STATE_INITIALIZED:
    543         case STATE_PAUSED:
    544             iState = STATE_STARTED;
    545             status = PVMFSuccess;
    546 
    547             break;
    548 
    549         default:
    550             status = PVMFErrInvalidState;
    551             break;
    552     }
    553 
    554     CommandResponse resp(status, cmdid, aContext);
    555     QueueCommandResponse(resp);
    556     return cmdid;
    557 }
    558 
    559 
    560 PVMFCommandId PVRefFileOutput::Pause(const OsclAny* aContext)
    561 {
    562     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::Pause() called"));
    563 
    564     PVMFCommandId cmdid = iCommandCounter++;
    565 
    566     PVMFStatus status = PVMFFailure;
    567 
    568     switch (iState)
    569     {
    570         case STATE_STARTED:
    571         case STATE_INITIALIZED:
    572         case STATE_PAUSED:
    573             iState = STATE_PAUSED;
    574             status = PVMFSuccess;
    575             break;
    576 
    577         default:
    578             status = PVMFErrInvalidState;
    579             break;
    580     }
    581 
    582     CommandResponse resp(status, cmdid, aContext);
    583     QueueCommandResponse(resp);
    584     return cmdid;
    585 }
    586 
    587 
    588 PVMFCommandId PVRefFileOutput::Flush(const OsclAny* aContext)
    589 {
    590     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::Flush() called"));
    591 
    592     PVMFCommandId cmdid = iCommandCounter++;
    593 
    594     PVMFStatus status = PVMFFailure;
    595 
    596     switch (iState)
    597     {
    598         case STATE_STARTED:
    599             iOutputFile.Flush();
    600             iState = STATE_INITIALIZED;
    601             status = PVMFSuccess;
    602             break;
    603 
    604         default:
    605             status = PVMFErrInvalidState;
    606             break;
    607     }
    608 
    609     CommandResponse resp(status, cmdid, aContext);
    610     QueueCommandResponse(resp);
    611     return cmdid;
    612 }
    613 
    614 PVMFCommandId PVRefFileOutput::DiscardData(const OsclAny* aContext)
    615 {
    616     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::DiscardData() called"));
    617 
    618     PVMFCommandId cmdid = iCommandCounter++;
    619 
    620     //this component doesn't buffer data, so there's nothing
    621     //needed here.
    622 
    623     PVMFStatus status = PVMFSuccess;
    624 
    625     CommandResponse resp(status, cmdid, aContext);
    626     QueueCommandResponse(resp);
    627     return cmdid;
    628 }
    629 
    630 PVMFCommandId PVRefFileOutput::DiscardData(PVMFTimestamp aTimestamp, const OsclAny* aContext)
    631 {
    632     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::DiscardData() called"));
    633 
    634     PVMFCommandId cmdid = iCommandCounter++;
    635 
    636     aTimestamp = 0;
    637 
    638     //this component doesn't buffer data, so there's nothing
    639     //needed here.
    640 
    641     PVMFStatus status = PVMFSuccess;
    642 
    643     CommandResponse resp(status, cmdid, aContext);
    644     QueueCommandResponse(resp);
    645     return cmdid;
    646 }
    647 
    648 PVMFCommandId PVRefFileOutput::Stop(const OsclAny* aContext)
    649 {
    650     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::Stop() called"));
    651 
    652     PVMFCommandId cmdid = iCommandCounter++;
    653 
    654     PVMFStatus status = PVMFFailure;
    655 
    656     switch (iState)
    657     {
    658         case STATE_STARTED:
    659         case STATE_PAUSED:
    660             // Add this case because of the following problem:
    661             // This mio component may delay its start until it does
    662             // configuration based on the first fragment it receives.
    663             // If the parent node is stopped before this fragment arrives
    664             // it will issue a stop command to this component, which
    665             // is still in the initialized state.  returning
    666             // PVMFErrInvalid state would be unnecessary here
    667             // when the component is already in the proper post-stop()
    668             // state.
    669         case STATE_INITIALIZED:
    670             iState = STATE_INITIALIZED;
    671             status = PVMFSuccess;
    672             break;
    673 
    674         default:
    675             status = PVMFErrInvalidState;
    676             break;
    677     }
    678 
    679     CommandResponse resp(status, cmdid, aContext);
    680     QueueCommandResponse(resp);
    681     return cmdid;
    682 }
    683 
    684 PVMFCommandId PVRefFileOutput::CancelAllCommands(const OsclAny* aContext)
    685 {
    686     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::CancelAllCommands() called"));
    687 
    688     PVMFCommandId cmdid = iCommandCounter++;
    689 
    690     //commands are executed immediately upon being received, so
    691     //it isn't really possible to cancel them.
    692 
    693     PVMFStatus status = PVMFSuccess;
    694 
    695     CommandResponse resp(status, cmdid, aContext);
    696     QueueCommandResponse(resp);
    697     return cmdid;
    698 }
    699 
    700 PVMFCommandId PVRefFileOutput::CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext)
    701 {
    702     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::CancelCommand() called"));
    703 
    704     PVMFCommandId cmdid = iCommandCounter++;
    705 
    706     //commands are executed immediately upon being received, so
    707     //it isn't really possible to cancel them.
    708 
    709     //see if the response is still queued.
    710     PVMFStatus status = PVMFFailure;
    711     for (uint32 i = 0; i < iCommandResponseQueue.size(); i++)
    712     {
    713         if (iCommandResponseQueue[i].iCmdId == aCmdId)
    714         {
    715             status = PVMFSuccess;
    716             break;
    717         }
    718     }
    719 
    720     CommandResponse resp(status, cmdid, aContext);
    721     QueueCommandResponse(resp);
    722     return cmdid;
    723 }
    724 
    725 void PVRefFileOutput::ThreadLogon()
    726 {
    727     if (iState == STATE_IDLE)
    728     {
    729         iLogger = PVLogger::GetLoggerObject("PVRefFileOutput");
    730         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::ThreadLogon() called"));
    731         AddToScheduler();
    732         iState = STATE_LOGGED_ON;
    733     }
    734 }
    735 
    736 
    737 void PVRefFileOutput::ThreadLogoff()
    738 {
    739     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::ThreadLogoff() called"));
    740     if (iState != STATE_IDLE)
    741     {
    742         RemoveFromScheduler();
    743         iLogger = NULL;
    744         iState = STATE_IDLE;
    745     }
    746 }
    747 
    748 
    749 void PVRefFileOutput::setPeer(PvmiMediaTransfer* aPeer)
    750 {
    751     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::setPeer() called"));
    752     // Set the observer
    753     iPeer = aPeer;
    754 }
    755 
    756 
    757 void PVRefFileOutput::useMemoryAllocators(OsclMemAllocator* write_alloc)
    758 {
    759     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::useMemoryAllocators() called"));
    760     //not supported.
    761     OSCL_UNUSED_ARG(write_alloc);
    762 }
    763 
    764 bool PVRefFileOutput::CheckWriteBusy(uint32 aSeqNum)
    765 //This routine will determine whether data can be accepted in a writeAsync
    766 //call and if not, will return true;
    767 {
    768     //we don't expect another data transfer when we're already busy.
    769     //but if it does occur, leave again.
    770     if (iWriteBusy)
    771     {
    772         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    773                         (0, "PVRefFileOutput::LeaveIfBusy: Unexpected call from peer!"));
    774         return true;
    775     }
    776 
    777     if (iActiveTiming)
    778     {
    779         //when doing active timing, impose a limit on the number
    780         //of queued messages.  otherwise the queue may grow without
    781         //bound since the caller is sending data ASAP.
    782         if (iWriteResponseQueue.size() >= iActiveTiming->iQueueLimit)
    783         {
    784             return true;
    785         }
    786     }
    787     else
    788     {
    789         //"sim flow control" is a test feature that causes this component
    790         //to simulate a busy condition on every 5th input buffer.
    791         if (iSimFlowControl
    792                 && aSeqNum != iWriteBusySeqNum
    793                 && ((aSeqNum + 1) % 5 == 0))
    794         {
    795             return true;
    796         }
    797     }
    798 
    799     //for all other cases, accept data now.
    800     return false;
    801 }
    802 
    803 void PVRefFileOutput::LogParameters()
    804 {
    805     iParametersLogged = true;
    806     if (iLogOutputToFile)
    807     {
    808         char string[128];
    809         int32 len;
    810         if (iVideoFormatString.get_size() > 0)
    811         {
    812             len = oscl_snprintf(string, 128, "Video Format %s ", iVideoFormatString.get_str());
    813             iOutputFile.Write(string, sizeof(uint8), len) ;
    814         }
    815         if (iVideoHeightValid)
    816         {
    817             len = oscl_snprintf(string, 128, "Video Height %d ", iVideoHeight);
    818             iOutputFile.Write(string, sizeof(uint8), len) ;
    819         }
    820         if (iVideoWidthValid)
    821         {
    822             len = oscl_snprintf(string, 128, "Video Width %d ", iVideoWidth);
    823             iOutputFile.Write(string, sizeof(uint8), len) ;
    824         }
    825         if (iVideoDisplayHeightValid)
    826         {
    827             len = oscl_snprintf(string, 128, "Video Display Height %d ", iVideoDisplayHeight);
    828             iOutputFile.Write(string, sizeof(uint8), len) ;
    829         }
    830         if (iVideoDisplayWidthValid)
    831         {
    832             len = oscl_snprintf(string, 128, "Video Display Width %d ", iVideoDisplayWidth);
    833             iOutputFile.Write(string, sizeof(uint8), len) ;
    834         }
    835         if (iAudioFormatString.get_size() > 0)
    836         {
    837             len = oscl_snprintf(string, 128, "Audio Format %s ", iAudioFormatString.get_str());
    838             iOutputFile.Write(string, sizeof(uint8), len) ;
    839         }
    840         if (iAudioNumChannelsValid)
    841         {
    842             len = oscl_snprintf(string, 128, "Audio Num Channels %d ", iAudioNumChannels);
    843             iOutputFile.Write(string, sizeof(uint8), len) ;
    844         }
    845         if (iAudioSamplingRateValid)
    846         {
    847             len = oscl_snprintf(string, 128, "Audio Sampling Rate %d ", iAudioSamplingRate);
    848             iOutputFile.Write(string, sizeof(uint8), len) ;
    849         }
    850         if (iTextFormatString.get_size() > 0)
    851         {
    852             len = oscl_snprintf(string, 128, "Text Format %s ", iTextFormatString.get_str());
    853             iOutputFile.Write(string, sizeof(uint8), len) ;
    854         }
    855     }
    856 }
    857 
    858 void PVRefFileOutput::LogCodecHeader(uint32 aSeqNum, const PVMFTimestamp& aTimestamp, uint32 datalen)
    859 {
    860     if (iLogOutputToFile)
    861     {
    862         if (iLogStrings)
    863         {
    864             char string[128];
    865             int32 len = oscl_snprintf(string, 128, "SeqNum %d Timestamp %d Len %d Codec Header", aSeqNum, aTimestamp, datalen);
    866             iOutputFile.Write(string, sizeof(uint8), len) ;
    867         }
    868         else
    869         {
    870             if (iVideoFormat == PVMF_MIME_H264_VIDEO_MP4)
    871             {
    872                 iOutputFile.Write(&datalen, sizeof(uint8), sizeof(uint32));
    873             }
    874         }
    875     }
    876 }
    877 
    878 void PVRefFileOutput::LogEndOfStream(uint32 aSeqNum, const PVMFTimestamp& aTimestamp)
    879 {
    880     if (iLogOutputToFile && iLogStrings)
    881     {
    882         char string[128];
    883         int32 len = oscl_snprintf(string, 128, "SeqNum %d Timestamp %d EOS", aSeqNum, aTimestamp);
    884         iOutputFile.Write(string, sizeof(uint8), len) ;
    885     }
    886 }
    887 
    888 void PVRefFileOutput::LogFrame(uint32 aSeqNum, const PVMFTimestamp& aTimestamp, uint32 datalen)
    889 {
    890     if (iLogOutputToFile)
    891     {
    892         if (iLogStrings)
    893         {
    894             char string[128];
    895             int32 len = oscl_snprintf(string, 128, "SeqNum %d Timestamp %d Len %d Frame", aSeqNum, aTimestamp, datalen);
    896             iOutputFile.Write(string, sizeof(uint8), len) ;
    897         }
    898         else
    899         {
    900             if (iVideoFormat == PVMF_MIME_H264_VIDEO_MP4)
    901             {
    902                 iOutputFile.Write(&datalen, sizeof(uint8), sizeof(uint32));
    903             }
    904         }
    905     }
    906 }
    907 
    908 PVMFCommandId PVRefFileOutput::writeAsync(uint8 aFormatType, int32 aFormatIndex, uint8* aData, uint32 aDataLen,
    909         const PvmiMediaXferHeader& data_header_info, OsclAny* aContext)
    910 {
    911     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    912                     (0, "PVRefFileOutput::writeAsync() seqnum %d ts %d context %d",
    913                      data_header_info.seq_num, data_header_info.timestamp, aContext));
    914 
    915     PVMFStatus status = PVMFFailure;
    916     bool discard = false;
    917 
    918     switch (aFormatType)
    919     {
    920         case PVMI_MEDIAXFER_FMT_TYPE_COMMAND :
    921             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    922                             (0, "PVRefFileOutput::writeAsync() called with Command info."));
    923             //ignore
    924             status = PVMFSuccess;
    925             break;
    926 
    927         case PVMI_MEDIAXFER_FMT_TYPE_NOTIFICATION :
    928             switch (aFormatIndex)
    929             {
    930                 case PVMI_MEDIAXFER_FMT_INDEX_END_OF_STREAM:
    931                 {
    932                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    933                                     (0, "PVRefFileOutput::writeAsync() called with Notification info - EOS."));
    934                     if (iLogStrings)
    935                     {
    936                         LogEndOfStream(data_header_info.seq_num, data_header_info.timestamp);
    937                     }
    938                     status = PVMFSuccess;
    939                 }
    940                 break;
    941                 case PVMI_MEDIAXFER_FMT_INDEX_RE_CONFIG_NOTIFICATION:
    942                 {
    943                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    944                                     (0, "PVRefFileOutput::writeAsync() called with Notification info - RECONFIG."));
    945                     status = HandleReConfig(data_header_info.seq_num);
    946                 }
    947                 break;
    948                 default:
    949                     //ignore
    950                     status = PVMFSuccess;
    951                     break;
    952             }
    953             break;
    954 
    955         case PVMI_MEDIAXFER_FMT_TYPE_DATA :
    956             switch (aFormatIndex)
    957             {
    958                 case PVMI_MEDIAXFER_FMT_INDEX_FMT_SPECIFIC_INFO:
    959                     //format-specific info contains codec headers.
    960                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
    961                                     (0, "PVRefFileOutput::writeAsync() called with format-specific info."));
    962 
    963                     if (iState < STATE_INITIALIZED)
    964                     {
    965                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    966                                         (0, "PVRefFileOutput::writeAsync: Error - Invalid state"));
    967                         iWriteBusy = true;
    968                         OSCL_LEAVE(OsclErrInvalidState);
    969                         return -1;
    970                     }
    971                     else
    972                     {
    973                         // Just write out the passed in data to file
    974                         if (iLogStrings)
    975                         {
    976                             if (!iParametersLogged)
    977                                 LogParameters();
    978                         }
    979                         if (aDataLen > 0)
    980                         {
    981                             LogCodecHeader(data_header_info.seq_num, data_header_info.timestamp, aDataLen);
    982                             if (iLogOutputToFile && iOutputFile.Write(aData, sizeof(uint8), aDataLen) != aDataLen)
    983                             {
    984                                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
    985                                                 (0, "PVRefFileOutput::writeAsync: Error - File write failed"));
    986                                 status = PVMFFailure;
    987                             }
    988                             else
    989                             {
    990                                 status = PVMFSuccess;
    991                             }
    992                         }
    993                         else
    994                         {
    995                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO,
    996                                             (0, "PVRefFileOutput::writeAsync() called aDataLen==0."));
    997                             status = PVMFSuccess;
    998                         }
    999                     }
   1000                     break;
   1001 
   1002                 case PVMI_MEDIAXFER_FMT_INDEX_DATA:
   1003                     //data contains the media bitstream.
   1004 
   1005                     //Verify the state
   1006                     if (iState != STATE_STARTED)
   1007                     {
   1008                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1009                                         (0, "PVRefFileOutput::writeAsync: Error - Invalid state"));
   1010                         iWriteBusy = true;
   1011                         OSCL_LEAVE(OsclErrInvalidState);
   1012                         return -1;
   1013                     }
   1014                     //Check whether we can accept data now and leave if we can't.
   1015                     else if (CheckWriteBusy(data_header_info.seq_num))
   1016                     {
   1017                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1018                                         (0, "PVRefFileOutput::writeAsync: Entering busy state"));
   1019 
   1020                         //schedule an event to re-start the data flow.
   1021                         iWriteBusy = true;
   1022                         iWriteBusySeqNum = data_header_info.seq_num;
   1023                         RunIfNotReady();
   1024 
   1025                         OSCL_LEAVE(OsclErrBusy);
   1026                     }
   1027                     else
   1028                     {
   1029                         // Just write out the passed in data to file
   1030                         if (iLogStrings)
   1031                         {
   1032                             if (!iParametersLogged)
   1033                             {
   1034                                 LogParameters();
   1035                             }
   1036                         }
   1037 
   1038                         if (aDataLen > 0)
   1039                         {
   1040                             //check whether the player clock is in frame-step mode.
   1041                             //do not render audio in frame-step mode.
   1042                             if (iAudioFormat != PVMF_MIME_FORMAT_UNKNOWN
   1043                                     && iActiveTiming
   1044                                     && iActiveTiming->FrameStepMode())
   1045                             {
   1046                                 discard = true;
   1047                             }
   1048 
   1049                             LogFrame(data_header_info.seq_num, data_header_info.timestamp, aDataLen);
   1050                             if (iTextFormat == PVMF_MIME_3GPP_TIMEDTEXT)
   1051                             {
   1052                                 // Guard against somebody setting this MIO component for multiple data types
   1053                                 OSCL_ASSERT(iVideoFormat == PVMF_MIME_FORMAT_UNKNOWN && iAudioFormat == PVMF_MIME_FORMAT_UNKNOWN);
   1054 
   1055                                 PVMFTimedTextMediaData* textmediadata = (PVMFTimedTextMediaData*)aData;
   1056 
   1057                                 // Write out the text sample entry
   1058                                 if (textmediadata->iTextSampleEntry.GetRep() != NULL)
   1059                                 {
   1060                                     // @todo Write out the text sample entry in a better format
   1061                                     if (iLogOutputToFile && iOutputFile.Write((OsclAny*)(textmediadata->iTextSampleEntry.GetRep()), sizeof(PVMFTimedTextSampleEntry), 1) != 1)
   1062                                     {
   1063                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1064                                                         (0, "PVRefFileOutput::writeAsync: Error - File write failed for text sample entry"));
   1065                                         status = PVMFFailure;
   1066                                         break;
   1067                                     }
   1068                                 }
   1069 
   1070                                 // Write out the raw text sample
   1071                                 if (iLogOutputToFile && iOutputFile.Write(textmediadata->iTextSample, sizeof(uint8), textmediadata->iTextSampleLength) != textmediadata->iTextSampleLength)
   1072                                 {
   1073                                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1074                                                     (0, "PVRefFileOutput::writeAsync: Error - File write failed for text sample data"));
   1075                                     status = PVMFFailure;
   1076                                 }
   1077                                 else
   1078                                 {
   1079                                     status = PVMFSuccess;
   1080                                 }
   1081                             }
   1082                             else if (discard)
   1083                             {
   1084                                 //do not render this frame.
   1085                                 char string[128];
   1086                                 int32 len = oscl_snprintf(string, 128, "discard-- frame-step mode");
   1087                                 if (iLogOutputToFile && iOutputFile.Write(string, sizeof(uint8), len) != (uint32)len)
   1088                                 {
   1089                                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1090                                                     (0, "PVRefFileOutput::writeAsync: Error - File write failed"));
   1091                                     status = PVMFFailure;
   1092                                 }
   1093                             }
   1094                             else
   1095                             {
   1096                                 if (iHeaderWritten != true && (iAudioFormat == PVMF_MIME_PCM16 || iAudioFormat == PVMF_MIME_PCM8))
   1097                                 {
   1098                                     if (iLogOutputToFile)
   1099                                     {
   1100                                         iOutputFile.Write(&iRIFFChunk, sizeof(uint8), sizeof(RIFFChunk));
   1101                                         iOutputFile.Write(&iFmtSubchunk, sizeof(uint8), sizeof(fmtSubchunk));
   1102                                         iOutputFile.Write(&iDataSubchunk, sizeof(uint8), sizeof(dataSubchunk));
   1103                                     }
   1104                                     iHeaderWritten = true;
   1105                                 }
   1106                                 if (iHeaderWritten != true && (iVideoFormat == PVMF_MIME_YUV420 || iVideoFormat == PVMF_MIME_YUV422))
   1107                                 {
   1108                                     WriteHeaders();
   1109                                     iHeaderWritten = true;
   1110                                 }
   1111 
   1112                                 if (iAudioFormat == PVMF_MIME_AMR_IETF ||
   1113                                         iAudioFormat == PVMF_MIME_AMR_IF2 ||
   1114                                         iVideoFormat == PVMF_MIME_H2631998 ||
   1115                                         iVideoFormat == PVMF_MIME_H2632000 ||
   1116                                         iVideoFormat == PVMF_MIME_M4V)
   1117                                 {
   1118                                     if (iLogOutputToFile && iOutputFile.Write(aData, sizeof(uint8), aDataLen) != aDataLen)
   1119                                     {
   1120                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1121                                                         (0, "PVRefFileOutput::writeAsync: Error - File write failed"));
   1122                                         status = PVMFFailure;
   1123                                     }
   1124                                     else
   1125                                     {
   1126                                         status = PVMFSuccess;
   1127                                     }
   1128                                 }
   1129                                 //'render' this frame
   1130                                 if (iAudioFormat == PVMF_MIME_PCM16 || iAudioFormat == PVMF_MIME_PCM8)
   1131                                 {
   1132                                     if (iLogOutputToFile && iOutputFile.Write(aData, sizeof(uint8), aDataLen) != aDataLen)
   1133                                     {
   1134                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1135                                                         (0, "PVRefFileOutput::writeAsync: Error - File write failed"));
   1136                                         status = PVMFFailure;
   1137                                     }
   1138                                     else
   1139                                     {
   1140                                         if (iAudioFormat == PVMF_MIME_PCM16 || iAudioFormat == PVMF_MIME_PCM8)
   1141                                             iDataSubchunk.subchunk2Size += aDataLen;
   1142                                         status = PVMFSuccess;
   1143                                     }
   1144                                 }
   1145 
   1146                                 if (iVideoFormat == PVMF_MIME_YUV420 || iVideoFormat == PVMF_MIME_YUV422)
   1147                                 {
   1148 #ifdef AVI_OUTPUT
   1149                                     unsigned char *u, *v, ch;
   1150                                     uint32 fsize = iVideoWidth * iVideoHeight;
   1151                                     uint32 bsize = iVideoWidth * iVideoHeight * 3 / 2;
   1152                                     u = aData + fsize;
   1153                                     v = aData + fsize * 5 / 4;
   1154                                     for (int j = 0; j < fsize / 4; j++)
   1155                                     {
   1156                                         ch = u[j];
   1157                                         u[j] = v[j];
   1158                                         v[j] = ch;
   1159                                     }
   1160                                     AddChunk(aData, bsize, videoChunkID);
   1161                                     iVideoLastTimeStamp = data_header_info.timestamp;
   1162                                     iAVIChunkSize += bsize + 4 + 4;
   1163                                     status = PVMFSuccess;
   1164 #else
   1165                                     uint32 size = iVideoWidth * iVideoHeight * 3 / 2;
   1166                                     if (iLogOutputToFile && iOutputFile.Write(aData, sizeof(uint8), size) != size)
   1167                                     {
   1168                                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1169                                                         (0, "PVRefFileOutput::writeAsync: Error - File write failed"));
   1170                                         status = PVMFFailure;
   1171                                     }
   1172                                     else
   1173                                         status = PVMFSuccess;
   1174 #endif
   1175                                 }
   1176                             }
   1177                         }
   1178                         else
   1179                         {
   1180                             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_INFO,
   1181                                             (0, "PVRefFileOutput::writeAsync() called aDataLen==0."));
   1182                             status = PVMFSuccess;
   1183                         }
   1184                     }
   1185                     break;
   1186 
   1187                 default:
   1188                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1189                                     (0, "PVRefFileOutput::writeAsync: Error - unrecognized format index"));
   1190                     status = PVMFFailure;
   1191                     break;
   1192             }
   1193             break;
   1194 
   1195         default:
   1196             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1197                             (0, "PVRefFileOutput::writeAsync: Error - unrecognized format type"));
   1198             status = PVMFFailure;
   1199             break;
   1200     }
   1201 
   1202     //Schedule asynchronous response
   1203     PVMFCommandId cmdid = iCommandCounter++;
   1204     WriteResponse resp(status, cmdid, aContext, data_header_info.timestamp, discard);
   1205     iWriteResponseQueue.push_back(resp);
   1206     RunIfNotReady();
   1207     return cmdid;
   1208 
   1209 }
   1210 
   1211 void PVRefFileOutput::writeComplete(PVMFStatus aStatus, PVMFCommandId  write_cmd_id, OsclAny* aContext)
   1212 {
   1213     OSCL_UNUSED_ARG(aStatus);
   1214     OSCL_UNUSED_ARG(write_cmd_id);
   1215     OSCL_UNUSED_ARG(aContext);
   1216 
   1217     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::writeComplete() called"));
   1218     //won't be called since this component is a sink.
   1219 
   1220 }
   1221 
   1222 
   1223 PVMFCommandId  PVRefFileOutput::readAsync(uint8* data, uint32 max_data_len, OsclAny* aContext,
   1224         int32* formats, uint16 num_formats)
   1225 {
   1226     OSCL_UNUSED_ARG(data);
   1227     OSCL_UNUSED_ARG(max_data_len);
   1228     OSCL_UNUSED_ARG(aContext);
   1229     OSCL_UNUSED_ARG(formats);
   1230     OSCL_UNUSED_ARG(num_formats);
   1231 
   1232     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::readAsync() called"));
   1233     //read not supported.
   1234     OsclError::Leave(OsclErrNotSupported);
   1235     return 0;
   1236 }
   1237 
   1238 
   1239 void PVRefFileOutput::readComplete(PVMFStatus aStatus, PVMFCommandId  read_cmd_id, int32 format_index,
   1240                                    const PvmiMediaXferHeader& data_header_info, OsclAny* aContext)
   1241 {
   1242     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::readComplete() called"));
   1243     //won't be called since this component is a sink.
   1244     OSCL_UNUSED_ARG(aStatus);
   1245     OSCL_UNUSED_ARG(read_cmd_id);
   1246     OSCL_UNUSED_ARG(format_index);
   1247     OSCL_UNUSED_ARG(data_header_info);
   1248     OSCL_UNUSED_ARG(aContext);
   1249 }
   1250 
   1251 
   1252 void PVRefFileOutput::statusUpdate(uint32 status_flags)
   1253 {
   1254     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::statusUpdate() called"));
   1255     //won't be called since this component is a sink.
   1256     OSCL_UNUSED_ARG(status_flags);
   1257 }
   1258 
   1259 
   1260 void PVRefFileOutput::cancelCommand(PVMFCommandId  command_id)
   1261 {
   1262     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::cancelCommand() called"));
   1263 
   1264     //the purpose of this API is to cancel a writeAsync command and report
   1265     //completion ASAP.
   1266 
   1267     //in this implementation, the write commands are executed immediately
   1268     //when received so it isn't really possible to cancel.
   1269     //just report completion immediately.
   1270 
   1271     for (uint32 i = 0; i < iWriteResponseQueue.size(); i++)
   1272     {
   1273         if (iWriteResponseQueue[i].iCmdId == command_id)
   1274         {
   1275             //report completion
   1276             if (iPeer)
   1277             {
   1278                 iPeer->writeComplete(iWriteResponseQueue[i].iStatus, iWriteResponseQueue[i].iCmdId, (OsclAny*)iWriteResponseQueue[i].iContext);
   1279             }
   1280             iWriteResponseQueue.erase(&iWriteResponseQueue[i]);
   1281             break;
   1282         }
   1283     }
   1284 }
   1285 
   1286 void PVRefFileOutput::cancelAllCommands()
   1287 {
   1288     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVRefFileOutput::cancelAllCommands() called"));
   1289 
   1290     //the purpose of this API is to cancel all writeAsync commands and report
   1291     //completion ASAP.
   1292 
   1293     //in this implementaiton, the write commands are executed immediately
   1294     //when received so it isn't really possible to cancel.
   1295     //just report completion immediately.
   1296 
   1297     while (iWriteResponseQueue.size() > 0)
   1298     {
   1299         //report completion
   1300         if (iPeer)
   1301         {
   1302             iPeer->writeComplete(iWriteResponseQueue[0].iStatus, iWriteResponseQueue[0].iCmdId, (OsclAny*)iWriteResponseQueue[0].iContext);
   1303         }
   1304         iWriteResponseQueue.erase(&iWriteResponseQueue[0]);
   1305     }
   1306 
   1307 }
   1308 
   1309 void PVRefFileOutput::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
   1310 {
   1311     OSCL_UNUSED_ARG(aObserver);
   1312     //not needed since this component only supports synchronous capability & config
   1313     //APIs.
   1314 }
   1315 
   1316 PVMFStatus PVRefFileOutput::getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier,
   1317         PvmiKvp*& aParameters, int& num_parameter_elements,
   1318         PvmiCapabilityContext aContext)
   1319 {
   1320     OSCL_UNUSED_ARG(aSession);
   1321     OSCL_UNUSED_ARG(aContext);
   1322 
   1323     if (pv_mime_strcmp(aIdentifier, INPUT_FORMATS_CAP_QUERY) == 0)
   1324     {
   1325         aParameters = NULL;
   1326         num_parameter_elements = 0;
   1327 
   1328         //This is a query for the list of supported formats.
   1329 
   1330         //This component supports any audio or video format
   1331 
   1332         //Generate a list of all the PVMF audio & video formats...
   1333         int32 count = 0;
   1334         if (iMediaType == MEDIATYPE_AUDIO)
   1335         {
   1336             if (iCompressedMedia)
   1337             {
   1338                 count = PVMF_SUPPORTED_COMPRESSED_AUDIO_FORMATS_COUNT;
   1339             }
   1340             else
   1341             {
   1342                 count = PVMF_SUPPORTED_UNCOMPRESSED_AUDIO_FORMATS_COUNT;
   1343             }
   1344         }
   1345         else if (iMediaType == MEDIATYPE_VIDEO)
   1346         {
   1347             if (iCompressedMedia)
   1348             {
   1349                 count = PVMF_SUPPORTED_COMPRESSED_VIDEO_FORMATS_COUNT;
   1350             }
   1351             else
   1352             {
   1353                 count = PVMF_SUPPORTED_UNCOMPRESSED_VIDEO_FORMATS_COUNT;
   1354             }
   1355         }
   1356         else if (iMediaType == MEDIATYPE_TEXT)
   1357         {
   1358             count = PVMF_SUPPORTED_TEXT_FORMAT_COUNT;
   1359         }
   1360         else
   1361         {
   1362             count = PVMF_SUPPORTED_UNCOMPRESSED_AUDIO_FORMATS_COUNT +
   1363                     PVMF_SUPPORTED_UNCOMPRESSED_VIDEO_FORMATS_COUNT +
   1364                     PVMF_SUPPORTED_COMPRESSED_AUDIO_FORMATS_COUNT +
   1365                     PVMF_SUPPORTED_COMPRESSED_VIDEO_FORMATS_COUNT +
   1366                     PVMF_SUPPORTED_TEXT_FORMAT_COUNT;
   1367         }
   1368 
   1369         aParameters = (PvmiKvp*)oscl_malloc(count * sizeof(PvmiKvp));
   1370 
   1371         if (aParameters)
   1372         {
   1373             PVMFFormatType fmt;
   1374             if (iMediaType == MEDIATYPE_AUDIO || iMediaType == MEDIATYPE_UNKNOWN)
   1375             {
   1376                 if (iCompressedMedia || iMediaType == MEDIATYPE_UNKNOWN)
   1377                 {
   1378                     int32 i = 0;
   1379                     if (iMediaType == MEDIATYPE_UNKNOWN)
   1380                     {
   1381                         i = num_parameter_elements;
   1382                     }
   1383 
   1384                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_AMR;
   1385                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_AMRWB;
   1386                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_AMR_IETF;
   1387                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_AMRWB_IETF;
   1388                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_AMR_IF2;
   1389                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_EVRC;
   1390                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_MP3;
   1391                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_ADIF;
   1392                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_ADTS;
   1393                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_LATM;
   1394                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_MPEG4_AUDIO;
   1395                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_G723;
   1396                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_G726;
   1397                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_WMA;
   1398                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_ASF_AMR;
   1399                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_REAL_AUDIO;
   1400                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_ASF_MPEG4_AUDIO;
   1401                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_3640;
   1402 
   1403                     while (i < count)
   1404                     {
   1405                         aParameters[i].key = (PvmiKeyType)oscl_malloc(oscl_strlen(MOUT_AUDIO_FORMAT_KEY) + 1);
   1406                         if (!aParameters[i].key)
   1407                         {
   1408                             return PVMFErrNoMemory;
   1409                             // (hope it's safe to leave array partially
   1410                             //  allocated, caller will free?)
   1411                         }
   1412                         oscl_strncpy(aParameters[i++].key, MOUT_AUDIO_FORMAT_KEY, oscl_strlen(MOUT_AUDIO_FORMAT_KEY) + 1);
   1413                     }
   1414                 }
   1415 
   1416                 if (!iCompressedMedia || iMediaType == MEDIATYPE_UNKNOWN)
   1417                 {
   1418                     int32 i = 0;
   1419                     if (iMediaType == MEDIATYPE_UNKNOWN)
   1420                     {
   1421                         i = num_parameter_elements;
   1422                     }
   1423 
   1424                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_PCM;
   1425                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_PCM8;
   1426                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_PCM16;
   1427                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_PCM16_BE;
   1428                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_ULAW;
   1429                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_ALAW;
   1430 
   1431                     while (i < count)
   1432                     {
   1433                         aParameters[i].key = (PvmiKeyType)oscl_malloc(oscl_strlen(MOUT_AUDIO_FORMAT_KEY) + 1);
   1434                         if (!aParameters[i].key)
   1435                         {
   1436                             return PVMFErrNoMemory;
   1437                             // (hope it's safe to leave array partially
   1438                             //  allocated, caller will free?)
   1439                         }
   1440                         oscl_strncpy(aParameters[i++].key, MOUT_AUDIO_FORMAT_KEY, oscl_strlen(MOUT_AUDIO_FORMAT_KEY) + 1);
   1441                     }
   1442                 }
   1443             }
   1444             if (iMediaType == MEDIATYPE_VIDEO || iMediaType == MEDIATYPE_UNKNOWN)
   1445             {
   1446                 if (iCompressedMedia || iMediaType == MEDIATYPE_UNKNOWN)
   1447                 {
   1448                     int32 i = 0;
   1449                     if (iMediaType == MEDIATYPE_UNKNOWN)
   1450                     {
   1451                         i = num_parameter_elements;
   1452                     }
   1453 
   1454                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_M4V;
   1455                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_H2631998;
   1456                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_H2632000;
   1457                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_H264_VIDEO_RAW;
   1458                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_H264_VIDEO_MP4;
   1459                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_H264_VIDEO;
   1460                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_WMV;
   1461                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_REAL_VIDEO;
   1462 
   1463                     while (i < count)
   1464                     {
   1465                         aParameters[i].key = (PvmiKeyType)oscl_malloc(oscl_strlen(MOUT_VIDEO_FORMAT_KEY) + 1);
   1466                         if (!aParameters[i].key)
   1467                         {
   1468                             return PVMFErrNoMemory;
   1469                             // (hope it's safe to leave array partially
   1470                             //  allocated, caller will free?)
   1471                         }
   1472                         oscl_strncpy(aParameters[i++].key, MOUT_VIDEO_FORMAT_KEY, oscl_strlen(MOUT_VIDEO_FORMAT_KEY) + 1);
   1473                     }
   1474                 }
   1475 
   1476                 if (!iCompressedMedia || iMediaType == MEDIATYPE_UNKNOWN)
   1477                 {
   1478                     int32 i = 0;
   1479                     if (iMediaType == MEDIATYPE_UNKNOWN)
   1480                     {
   1481                         i = num_parameter_elements;
   1482                     }
   1483 
   1484                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_YUV420;
   1485                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_YUV422;
   1486                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_RGB8;
   1487                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_RGB12;
   1488                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_RGB16;
   1489                     aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_RGB24;
   1490 
   1491                     while (i < count)
   1492                     {
   1493                         aParameters[i].key = (PvmiKeyType)oscl_malloc(oscl_strlen(MOUT_VIDEO_FORMAT_KEY) + 1);
   1494                         if (!aParameters[i].key)
   1495                         {
   1496                             return PVMFErrNoMemory;
   1497                             // (hope it's safe to leave array partially
   1498                             //  allocated, caller will free?)
   1499                         }
   1500                         oscl_strncpy(aParameters[i++].key, MOUT_VIDEO_FORMAT_KEY, oscl_strlen(MOUT_VIDEO_FORMAT_KEY) + 1);
   1501                     }
   1502                 }
   1503             }
   1504 
   1505             if (iMediaType == MEDIATYPE_TEXT || iMediaType == MEDIATYPE_UNKNOWN)
   1506             {
   1507                 int32 i = 0;
   1508                 if (iMediaType == MEDIATYPE_UNKNOWN)
   1509                 {
   1510                     i = num_parameter_elements;
   1511                 }
   1512 
   1513                 aParameters[num_parameter_elements++].value.pChar_value = (char*)PVMF_MIME_3GPP_TIMEDTEXT;
   1514                 aParameters[i].key = (PvmiKeyType)oscl_malloc(oscl_strlen(MOUT_TEXT_FORMAT_KEY) + 1);
   1515                 if (!aParameters[i].key)
   1516                 {
   1517                     return PVMFErrNoMemory;
   1518                     // (hope it's safe to leave array partially
   1519                     //  allocated, caller will free?)
   1520                 }
   1521                 oscl_strncpy(aParameters[i++].key, MOUT_TEXT_FORMAT_KEY, oscl_strlen(MOUT_TEXT_FORMAT_KEY) + 1);
   1522             }
   1523             return PVMFSuccess;
   1524         }
   1525         return PVMFErrNoMemory;
   1526     }
   1527     else if (pv_mime_strcmp(aIdentifier, PVMF_NUM_DECODED_FRAMES_CONFIG_KEY) == 0)
   1528     {
   1529         aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
   1530         if (!aParameters)
   1531         {
   1532             return PVMFErrNoMemory;
   1533         }
   1534 
   1535         aParameters[0].value.uint32_value = DEFAULT_NUM_DECODED_FRAMES_CAPABILITY;
   1536         return PVMFSuccess;
   1537     }
   1538 #if TEST_BUFFER_ALLOCATOR
   1539     else if (pv_mime_strcmp(aIdentifier, PVMF_BUFFER_ALLOCATOR_KEY) == 0)
   1540     {
   1541         int32 err;
   1542         aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
   1543         if (!aParameters)
   1544         {
   1545             return PVMFErrNoMemory;
   1546         }
   1547 
   1548         OSCL_TRY(err, aParameters[0].value.key_specific_value = (PVInterface *)OSCL_NEW(PVRefBufferAlloc, (iBufferSize, iNumberOfBuffers)) ;);
   1549         if (err || (NULL == aParameters[0].value.key_specific_value))
   1550         {
   1551             return PVMFErrNoMemory;
   1552 
   1553         }
   1554         return PVMFSuccess;
   1555     }
   1556 #endif
   1557     //other queries are not currently supported.
   1558 
   1559     //unrecognized key.
   1560     return PVMFFailure;
   1561 }
   1562 
   1563 PVMFStatus PVRefFileOutput::releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
   1564 {
   1565     OSCL_UNUSED_ARG(aSession);
   1566 
   1567     //release parameters that were allocated by this component.
   1568     if (aParameters)
   1569     {
   1570         for (int i = 0; i < num_elements; i++)
   1571         {
   1572             oscl_free(aParameters[i].key);
   1573         }
   1574         oscl_free(aParameters);
   1575         return PVMFSuccess;
   1576     }
   1577     return PVMFFailure;
   1578 }
   1579 
   1580 void PVRefFileOutput::createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
   1581 {
   1582     OSCL_UNUSED_ARG(aSession);
   1583     OSCL_UNUSED_ARG(aContext);
   1584 
   1585     OsclError::Leave(OsclErrNotSupported);
   1586 }
   1587 
   1588 void PVRefFileOutput::setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext,
   1589         PvmiKvp* aParameters, int num_parameter_elements)
   1590 {
   1591     OSCL_UNUSED_ARG(aSession);
   1592     OSCL_UNUSED_ARG(aContext);
   1593     OSCL_UNUSED_ARG(aParameters);
   1594     OSCL_UNUSED_ARG(num_parameter_elements);
   1595 
   1596     OsclError::Leave(OsclErrNotSupported);
   1597 }
   1598 
   1599 void PVRefFileOutput::DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext)
   1600 {
   1601     OSCL_UNUSED_ARG(aSession);
   1602     OSCL_UNUSED_ARG(aContext);
   1603 
   1604     OsclError::Leave(OsclErrNotSupported);
   1605 }
   1606 
   1607 
   1608 void PVRefFileOutput::setParametersSync(PvmiMIOSession aSession,
   1609                                         PvmiKvp* aParameters,
   1610                                         int num_elements,
   1611                                         PvmiKvp * & aRet_kvp)
   1612 {
   1613     OSCL_UNUSED_ARG(aSession);
   1614     aRet_kvp = NULL;
   1615 
   1616     for (int32 i = 0; i < num_elements; i++)
   1617     {
   1618         //Check against known audio parameter keys...
   1619         if (pv_mime_strcmp(aParameters[i].key, MOUT_AUDIO_FORMAT_KEY) == 0)
   1620         {
   1621             if (oscl_strncmp(aParameters[i].value.pChar_value, "audio/L16", sizeof("audio/L16")) == 0)
   1622                 iAudioFormat = PVMF_MIME_PCM16;
   1623             else if (oscl_strncmp(aParameters[i].value.pChar_value, "audio/L8", sizeof("audio/L8")) == 0)
   1624                 iAudioFormat = PVMF_MIME_PCM8;
   1625             else if (oscl_strncmp(aParameters[i].value.pChar_value, "X-AMR-IF2", sizeof("X-AMR-IF2")) == 0)
   1626                 iAudioFormat = PVMF_MIME_AMR_IF2;
   1627             else if (oscl_strncmp(aParameters[i].value.pChar_value, "X-AMR-IETF-SEPARATE", sizeof("X-AMR-IETF-SEPARATE")) == 0)
   1628                 iAudioFormat = PVMF_MIME_AMR_IETF;
   1629 
   1630             iAudioFormatString = iAudioFormat.getMIMEStrPtr();
   1631             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1632                             (0, "PVRefFileOutput::setParametersSync() Audio Format Key, Value %s", iAudioFormatString.get_str()));
   1633         }
   1634         else if (pv_mime_strcmp(aParameters[i].key, MOUT_AUDIO_SAMPLING_RATE_KEY) == 0)
   1635         {
   1636             iAudioSamplingRate = (int32)aParameters[i].value.uint32_value;
   1637             iAudioSamplingRateValid = true;
   1638             iFmtSubchunk.sampleRate = iAudioSamplingRate;
   1639             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1640                             (0, "PVRefFileOutput::setParametersSync() Audio Sampling Rate Key, Value %d", iAudioSamplingRate));
   1641         }
   1642         else if (pv_mime_strcmp(aParameters[i].key, MOUT_AUDIO_NUM_CHANNELS_KEY) == 0)
   1643         {
   1644             iAudioNumChannels = (int32)aParameters[i].value.uint32_value;
   1645             iAudioNumChannelsValid = true;
   1646             iFmtSubchunk.numChannels = iAudioNumChannels;
   1647             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1648                             (0, "PVRefFileOutput::setParametersSync() Audio Num Channels Key, Value %d", iAudioNumChannels));
   1649         }
   1650         //Check against known video parameter keys...
   1651         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_FORMAT_KEY) == 0)
   1652         {
   1653 
   1654             if (oscl_strncmp(aParameters[i].value.pChar_value, "X-YUV-420", sizeof("X-YUV-420")) == 0)
   1655                 iVideoFormat = PVMF_MIME_YUV420;
   1656             else if (oscl_strncmp(aParameters[i].value.pChar_value, "X-YUV-422", sizeof("X-YUV-422")) == 0)
   1657                 iVideoFormat = PVMF_MIME_YUV422;
   1658             else if (oscl_strncmp(aParameters[i].value.pChar_value, "video/H263-2000", sizeof("video/H263-2000")) == 0)
   1659                 iVideoFormat = PVMF_MIME_H2632000;
   1660             else if (oscl_strncmp(aParameters[i].value.pChar_value, "video/H263-1998", sizeof("video/H263-1998")) == 0)
   1661                 iVideoFormat = PVMF_MIME_H2631998;
   1662             else if (oscl_strncmp(aParameters[i].value.pChar_value, "video/MP4V-ES", sizeof("video/MP4V-ES")) == 0)
   1663                 iVideoFormat = PVMF_MIME_M4V;
   1664 
   1665             iVideoFormatString = iVideoFormat.getMIMEStrPtr();
   1666             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1667                             (0, "PVRefFileOutput::setParametersSync() Video Format Key, Value %s", iVideoFormatString.get_str()));
   1668         }
   1669         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_WIDTH_KEY) == 0)
   1670         {
   1671             iVideoWidth = (int32)aParameters[i].value.uint32_value;
   1672             iVideoWidthValid = true;
   1673             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1674                             (0, "PVRefFileOutput::setParametersSync() Video Width Key, Value %d", iVideoWidth));
   1675         }
   1676         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_HEIGHT_KEY) == 0)
   1677         {
   1678             iVideoHeight = (int32)aParameters[i].value.uint32_value;
   1679             iVideoHeightValid = true;
   1680             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1681                             (0, "PVRefFileOutput::setParametersSync() Video Height Key, Value %d", iVideoHeight));
   1682         }
   1683         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_HEIGHT_KEY) == 0)
   1684         {
   1685             iVideoDisplayHeight = (int32)aParameters[i].value.uint32_value;
   1686             iVideoDisplayHeightValid = true;
   1687             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1688                             (0, "PVRefFileOutput::setParametersSync() Video Display Height Key, Value %d", iVideoDisplayHeight));
   1689         }
   1690         else if (pv_mime_strcmp(aParameters[i].key, MOUT_VIDEO_DISPLAY_WIDTH_KEY) == 0)
   1691         {
   1692             iVideoDisplayWidth = (int32)aParameters[i].value.uint32_value;
   1693             iVideoDisplayWidthValid = true;
   1694             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1695                             (0, "PVRefFileOutput::setParametersSync() Video Display Width Key, Value %d", iVideoDisplayWidth));
   1696         }
   1697         //Check against known text parameter keys...
   1698         else if (pv_mime_strcmp(aParameters[i].key, MOUT_TEXT_FORMAT_KEY) == 0)
   1699         {
   1700             iTextFormatString = aParameters[i].value.pChar_value;
   1701             iTextFormat = iTextFormatString.get_str();
   1702             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1703                             (0, "PVRefFileOutput::setParametersSync() Text Format Key, Value %s", iTextFormatString.get_str()));
   1704         }
   1705         // Change to output rate
   1706         else if (pv_mime_strcmp(aParameters[i].key, MOUT_MEDIAXFER_OUTPUT_RATE) == 0)
   1707         {
   1708             // Do nothing, this setting is meaningless for file IO
   1709             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1710                             (0, "PVRefFileOutput::setParametersSync() MediaXFER Output Rate Key, Value %d",
   1711                              aParameters[i].value.int32_value));
   1712         }
   1713         else if (pv_mime_strcmp(aParameters[i].key, PVMF_FORMAT_SPECIFIC_INFO_KEY) == 0)
   1714         {
   1715             if (!iFileOpened)
   1716             {
   1717                 if (iOutputFile.Open(iOutputFileName.get_cstr(), Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY, iFs) != 0)
   1718                 {
   1719                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1720                                     (0, "PVRefFileOutput::setParametersSync: Error - File Open failed"));
   1721                 }
   1722                 else
   1723                 {
   1724                     iFileOpened = true;
   1725                     LogCodecHeader(0, 0, (int32)aParameters[i].capacity);
   1726                     if (aParameters[i].value.pChar_value != NULL)
   1727                     {
   1728                         if (iLogOutputToFile && iOutputFile.Write(aParameters[i].value.pChar_value,
   1729                                 sizeof(uint8),
   1730                                 (int32)aParameters[i].capacity) != (uint32)aParameters[i].length)
   1731                         {
   1732                             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
   1733                                             (0, "PVRefFileOutput::setParametersSync: Error - File write failed"));
   1734                         }
   1735                     }
   1736                 }
   1737             }
   1738         }
   1739         //All FSI for video will be set here in one go
   1740         else if (pv_mime_strcmp(aParameters[i].key, PVMF_FORMAT_SPECIFIC_INFO_KEY_YUV) == 0)
   1741         {
   1742             uint8* data = (uint8*)aParameters->value.key_specific_value;
   1743             PVMFYuvFormatSpecificInfo0* yuvInfo = (PVMFYuvFormatSpecificInfo0*)data;
   1744 
   1745             iVideoWidth = (int32)yuvInfo->width;
   1746             iVideoWidthValid = true;
   1747             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1748                             (0, "PVRefFileOutput::setParametersSync() Video Width, Value %d", iVideoWidth));
   1749 
   1750             iVideoHeight = (int32)yuvInfo->height;
   1751             iVideoHeightValid = true;
   1752             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1753                             (0, "PVRefFileOutput::setParametersSync() Video Height, Value %d", iVideoHeight));
   1754 
   1755             iVideoDisplayHeight = (int32)yuvInfo->display_height;
   1756             iVideoDisplayHeightValid = true;
   1757             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1758                             (0, "PVRefFileOutput::setParametersSync() Video Display Height, Value %d", iVideoDisplayHeight));
   1759 
   1760 
   1761             iVideoDisplayWidth = (int32)yuvInfo->display_width;
   1762             iVideoDisplayWidthValid = true;
   1763             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1764                             (0, "PVRefFileOutput::setParametersSync() Video Display Width, Value %d", iVideoDisplayWidth));
   1765 
   1766             iNumberOfBuffers = (int32)yuvInfo->num_buffers;
   1767             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1768                             (0, "PVRefFileOutput::setParametersSync() Number of Buffer, Value %d", iNumberOfBuffers));
   1769 
   1770             iBufferSize = (int32)yuvInfo->buffer_size;
   1771             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1772                             (0, "PVRefFileOutput::setParametersSync() Buffer Size, Value %d", iBufferSize));
   1773 
   1774         }
   1775         //All FSI for audio will be set here in one go
   1776         else if (pv_mime_strcmp(aParameters[i].key, PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM) == 0)
   1777         {
   1778             uint8* data = (uint8*)aParameters->value.key_specific_value;
   1779             channelSampleInfo* pcm16Info = (channelSampleInfo*)data;
   1780 
   1781             iAudioSamplingRate = pcm16Info->samplingRate;
   1782             iAudioSamplingRateValid = true;
   1783             iFmtSubchunk.sampleRate = iAudioSamplingRate;
   1784             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1785                             (0, "PVRefFileOutput::setParametersSync() Audio Sampling Rate, Value %d", iAudioSamplingRate));
   1786 
   1787 
   1788             iAudioNumChannels = pcm16Info->desiredChannels;
   1789             iAudioNumChannelsValid = true;
   1790             iFmtSubchunk.numChannels = iAudioNumChannels;
   1791             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1792                             (0, "PVRefFileOutput::setParametersSync() Audio Num Channels, Value %d", iAudioNumChannels));
   1793 
   1794 
   1795             iFmtSubchunk.bitsPerSample = (int32)pcm16Info->bitsPerSample;
   1796             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1797                             (0, "PVRefFileOutput::setParametersSync() Audio Bits Per Sample, Value %d", iFmtSubchunk.bitsPerSample));
   1798 
   1799             iNumberOfBuffers = (int32)pcm16Info->num_buffers;
   1800             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1801                             (0, "PVRefFileOutput::setParametersSync() Number of Buffer, Value %d", iNumberOfBuffers));
   1802 
   1803             iBufferSize = (int32)pcm16Info->buffer_size;
   1804             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1805                             (0, "PVRefFileOutput::setParametersSync() Buffer Size, Value %d", iBufferSize));
   1806 
   1807         }
   1808         else
   1809         {
   1810             //if we get here the key is unrecognized.
   1811             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   1812                             (0, "PVRefFileOutput::setParametersSync() Error, unrecognized key "));
   1813 
   1814             //set the return value to indicate the unrecognized key
   1815             //and return.
   1816             aRet_kvp = &aParameters[i];
   1817             return;
   1818         }
   1819     }
   1820     if (iAudioFormat == PVMF_MIME_PCM16)
   1821     {
   1822         iFmtSubchunk.bitsPerSample = 16;
   1823         iFmtSubchunk.byteRate = iFmtSubchunk.sampleRate * iFmtSubchunk.numChannels * iFmtSubchunk.bitsPerSample / 8;
   1824         iFmtSubchunk.blockAlign = iFmtSubchunk.numChannels * iFmtSubchunk.bitsPerSample / 8;
   1825     }
   1826     else
   1827     {
   1828         iFmtSubchunk.bitsPerSample = 8;
   1829         iFmtSubchunk.byteRate = iFmtSubchunk.sampleRate * iFmtSubchunk.numChannels * iFmtSubchunk.bitsPerSample / 8;
   1830         iFmtSubchunk.blockAlign = iFmtSubchunk.numChannels * iFmtSubchunk.bitsPerSample / 8;
   1831 
   1832     }
   1833 
   1834     if ((iVideoFormat == PVMF_MIME_YUV420 || iVideoFormat == PVMF_MIME_YUV422) && (iVideoHeightValid == true && iVideoHeightValid == true && iInitializeAVIDone == false))
   1835     {
   1836         InitializeAVI(iVideoWidth, iVideoHeight);
   1837         iInitializeAVIDone = true;
   1838     }
   1839 
   1840     //No configuration is required for this MIO to function.
   1841     //So, send PVMFMIOConfigurationComplete() from Run()
   1842 
   1843     //If MIO is configured, send PVMFMIOConfigurationComplete event to observer.
   1844     if (!iIsMIOConfigured)
   1845     {
   1846         if (iObserver)
   1847         {
   1848             iObserver->ReportInfoEvent(PVMFMIOConfigurationComplete);
   1849             iIsMIOConfigured = true;
   1850         }
   1851     }
   1852 }
   1853 
   1854 PVMFCommandId PVRefFileOutput::setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters,
   1855         int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context)
   1856 {
   1857     OSCL_UNUSED_ARG(aSession);
   1858     OSCL_UNUSED_ARG(aParameters);
   1859     OSCL_UNUSED_ARG(num_elements);
   1860     OSCL_UNUSED_ARG(aRet_kvp);
   1861     OSCL_UNUSED_ARG(context);
   1862 
   1863     OsclError::Leave(OsclErrNotSupported);
   1864     return 0;
   1865 }
   1866 
   1867 uint32 PVRefFileOutput::getCapabilityMetric(PvmiMIOSession aSession)
   1868 {
   1869     OSCL_UNUSED_ARG(aSession);
   1870 
   1871     return 0;
   1872 }
   1873 
   1874 PVMFStatus PVRefFileOutput::verifyParametersSync(PvmiMIOSession aSession,
   1875         PvmiKvp* aParameters,
   1876         int num_elements)
   1877 {
   1878     OSCL_UNUSED_ARG(aSession);
   1879 
   1880     // Go through each parameter
   1881     for (int32 paramind = 0; paramind < num_elements; ++paramind)
   1882     {
   1883         // Retrieve the first component from the key string
   1884         char* compstr = NULL;
   1885         pv_mime_string_extract_type(0, aParameters[paramind].key, compstr);
   1886 
   1887         if (pv_mime_strcmp(compstr, _STRLIT_CHAR("x-pvmf/media/format-type")) == 0)
   1888         {
   1889             if (iMediaType == MEDIATYPE_UNKNOWN)
   1890             {
   1891                 // For an unknown media type return PVMFErrNotSupported always.
   1892                 return PVMFErrNotSupported;
   1893             }
   1894 
   1895             if (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_FORMAT_UNKNOWN) == 0)
   1896             {
   1897                 return PVMFErrNotSupported;
   1898             }
   1899 
   1900             // The Sink will return success based on following conditions:
   1901             // i) The MIME string is supported by the sink, Text Sink will support Text MIME,
   1902             //    Audio Sink - Audio MIME and Video Sink - Video MIME.
   1903             // ii) For all compressed formats, if the sink itself is Compressed. If the sink
   1904             //      is UnCompressed here, Sink will send PVMFErrNotSupported.
   1905             // iii) For all uncompressed formats, if the sink itself is Uncompressed. If the sink
   1906             //      is Compressed here, Sink will send PVMFErrNotSupported.
   1907             if (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_3GPP_TIMEDTEXT) == 0)
   1908             {
   1909                 if (iMediaType == MEDIATYPE_TEXT)
   1910                 {
   1911                     return PVMFSuccess;
   1912                 }
   1913                 else
   1914                 {
   1915                     return PVMFErrNotSupported;
   1916                 }
   1917             }
   1918             else if ((pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_YUV420) == 0) ||
   1919                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_YUV422) == 0) ||
   1920                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_RGB8) == 0) ||
   1921                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_RGB12) == 0) ||
   1922                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_RGB16) == 0) ||
   1923                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_RGB24) == 0))
   1924             {
   1925                 // Uncompressed Video formats
   1926                 if (iMediaType == MEDIATYPE_VIDEO)
   1927                 {
   1928                     if (iCompressedMedia)
   1929                     {
   1930                         return PVMFErrNotSupported;
   1931                     }
   1932                     else
   1933                     {
   1934                         return PVMFSuccess;
   1935                     }
   1936                 }
   1937                 else
   1938                 {
   1939                     return PVMFErrNotSupported;
   1940                 }
   1941             }
   1942             else if ((pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_M4V) == 0) ||
   1943                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_H2631998) == 0) ||
   1944                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_H2632000) == 0) ||
   1945                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_H264_VIDEO_RAW) == 0) ||
   1946                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_H264_VIDEO_MP4) == 0) ||
   1947                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_H264_VIDEO) == 0) ||
   1948                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_WMV) == 0) ||
   1949                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_REAL_VIDEO) == 0))
   1950             {
   1951                 // Compressed Video formats
   1952                 if (iMediaType == MEDIATYPE_VIDEO)
   1953                 {
   1954                     if (iCompressedMedia)
   1955                     {
   1956                         return PVMFSuccess;
   1957                     }
   1958                     else
   1959                     {
   1960                         return PVMFErrNotSupported;
   1961                     }
   1962                 }
   1963                 else
   1964                 {
   1965                     return PVMFErrNotSupported;
   1966                 }
   1967             }
   1968             else if ((pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_PCM) == 0) ||
   1969                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_PCM8) == 0) ||
   1970                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_PCM16) == 0) ||
   1971                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_PCM16_BE) == 0) ||
   1972                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_ULAW) == 0) ||
   1973                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_ALAW) == 0))
   1974             {
   1975                 // Uncompressed Audio formats
   1976                 if (iMediaType == MEDIATYPE_AUDIO)
   1977                 {
   1978                     if (iCompressedMedia)
   1979                     {
   1980                         return PVMFErrNotSupported;
   1981                     }
   1982                     else
   1983                     {
   1984                         return PVMFSuccess;
   1985                     }
   1986                 }
   1987                 else
   1988                 {
   1989                     return PVMFErrNotSupported;
   1990                 }
   1991             }
   1992             else if ((pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_AMR) == 0) ||
   1993                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_AMRWB) == 0) ||
   1994                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_AMR_IETF) == 0) ||
   1995                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_AMRWB_IETF) == 0) ||
   1996                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_AMR_IF2) == 0) ||
   1997                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_EVRC) == 0) ||
   1998                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_MP3) == 0) ||
   1999                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_ADIF) == 0) ||
   2000                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_ADTS) == 0) ||
   2001                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_LATM) == 0) ||
   2002                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_MPEG4_AUDIO) == 0) ||
   2003                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_G723) == 0) ||
   2004                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_G726) == 0) ||
   2005                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_WMA) == 0) ||
   2006                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_ASF_AMR) == 0) ||
   2007                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_REAL_AUDIO) == 0) ||
   2008                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_ASF_MPEG4_AUDIO) == 0) ||
   2009                      (pv_mime_strcmp(aParameters[paramind].value.pChar_value, PVMF_MIME_3640) == 0))
   2010             {
   2011                 // Compressed audio formats
   2012                 if (iMediaType == MEDIATYPE_AUDIO)
   2013                 {
   2014                     if (iCompressedMedia)
   2015                     {
   2016                         return PVMFSuccess;
   2017                     }
   2018                     else
   2019                     {
   2020                         return PVMFErrNotSupported;
   2021                     }
   2022                 }
   2023                 else
   2024                 {
   2025                     return PVMFErrNotSupported;
   2026                 }
   2027             }
   2028         }
   2029     }
   2030 
   2031     // For all other parameters return a default success
   2032 
   2033     return PVMFSuccess;
   2034 }
   2035 
   2036 void PVRefFileOutput::setFormatMask(uint32 mask)
   2037 {
   2038     iFormatMask = mask;
   2039 }
   2040 
   2041 OSCL_EXPORT_REF PVMFStatus PVRefFileOutput::SetClock(PVMFMediaClock *clockVal)
   2042 {
   2043     iClock = clockVal;
   2044     return PVMFSuccess;
   2045 }
   2046 
   2047 OSCL_EXPORT_REF void PVRefFileOutput::addRef()
   2048 {
   2049 }
   2050 
   2051 OSCL_EXPORT_REF void PVRefFileOutput::removeRef()
   2052 {
   2053 }
   2054 
   2055 OSCL_EXPORT_REF bool PVRefFileOutput::queryInterface(const PVUuid& aUuid, PVInterface*& aInterface)
   2056 {
   2057     OSCL_UNUSED_ARG(aInterface);
   2058     OSCL_UNUSED_ARG(aUuid);
   2059     return true;
   2060 }
   2061 void PVRefFileOutput::queryUuid(PVUuid& uuid)
   2062 {
   2063     OSCL_UNUSED_ARG(uuid);
   2064 }
   2065 //
   2066 // For active timing support
   2067 //
   2068 OSCL_EXPORT_REF PVMFStatus PVRefFileOutputActiveTimingSupport::SetClock(PVMFMediaClock *clockVal)
   2069 {
   2070     iClock = clockVal;
   2071     return PVMFSuccess;
   2072 }
   2073 
   2074 OSCL_EXPORT_REF void PVRefFileOutputActiveTimingSupport::addRef()
   2075 {
   2076 }
   2077 
   2078 OSCL_EXPORT_REF void PVRefFileOutputActiveTimingSupport::removeRef()
   2079 {
   2080 }
   2081 
   2082 OSCL_EXPORT_REF bool PVRefFileOutputActiveTimingSupport::queryInterface(const PVUuid& aUuid, PVInterface*& aInterface)
   2083 {
   2084     aInterface = NULL;
   2085     PVUuid uuid;
   2086     queryUuid(uuid);
   2087     if (uuid == aUuid)
   2088     {
   2089         PvmiClockExtensionInterface* myInterface = OSCL_STATIC_CAST(PvmiClockExtensionInterface*, this);
   2090         aInterface = OSCL_STATIC_CAST(PVInterface*, myInterface);
   2091         return true;
   2092     }
   2093     return false;
   2094 }
   2095 
   2096 void PVRefFileOutputActiveTimingSupport::queryUuid(PVUuid& uuid)
   2097 {
   2098     uuid = PvmiClockExtensionInterfaceUuid;
   2099 }
   2100 
   2101 bool PVRefFileOutputActiveTimingSupport::FrameStepMode()
   2102 {
   2103     if (iClock && iClock->GetCountTimebase())
   2104     {
   2105         //frame-step mode detected!
   2106 
   2107         //there will be a discontinuity in the rendering-- so reset the
   2108         //simulated delay control now.
   2109         if (iLastTimestampValid)
   2110         {
   2111             iLastTimestampValid = false;
   2112         }
   2113         return true;
   2114     }
   2115     return false;
   2116 }
   2117 
   2118 void PVRefFileOutputActiveTimingSupport::AdjustClock(PVMFTimestamp& aTs)
   2119 {
   2120     //Adjust player clock to match rendering time.
   2121     //This is called at the time of simulated rendering.
   2122     //On a real device, we would read the rendering position from the device.
   2123     //In this simulation, we just assume that data is rendered ASAP and there
   2124     //is no drift in the rendering device clock.
   2125     //Therefore we just set the player clock to match the media timestamp at
   2126     //the time of simulated rendering.
   2127     //However, only adjust the clock ahead when in frame step mode
   2128 
   2129     if (iClock)
   2130     {
   2131         uint32 clktime;
   2132         uint32 tbtime;
   2133         bool overflow = 0;
   2134         iClock->GetCurrentTime32(clktime, overflow, PVMF_MEDIA_CLOCK_MSEC, tbtime);
   2135         {
   2136             // always adjust clock if not in frame step mode
   2137             // if in framestep mode, only adjust clock if the timestamp is ahead
   2138             bool frameStep = FrameStepMode();
   2139             if (!frameStep || (frameStep && (aTs > (PVMFTimestamp)clktime)))
   2140             {
   2141                 if (!iLogger)
   2142                 {
   2143                     iLogger = PVLogger::GetLoggerObject("PVRefFileOutput");
   2144                 }
   2145                 uint32 adjtime = aTs;
   2146                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
   2147                                 (0, "PVRefFileOutputActiveTimingSupport::AdjustClock: from %d to %d", (uint32)clktime, (uint32)adjtime));
   2148                 iClock->AdjustClockTime32(clktime, tbtime, adjtime, PVMF_MEDIA_CLOCK_MSEC, overflow);
   2149             }
   2150         }
   2151     }
   2152 }
   2153 
   2154 //This routine does 2 things-- computes the delay before we can render this frame,
   2155 //based on simulated rendering time for the prior frame, and adjusts the
   2156 //player clock when it's time to render this frame.
   2157 uint32 PVRefFileOutputActiveTimingSupport::GetDelayMsec(PVMFTimestamp& aTs)
   2158 {
   2159     //This routine can be called twice per frame.  On the first call, if
   2160     //a non-zero delay is returned, it will be called a second time after the delay
   2161     //has elapsed.
   2162 
   2163     if (iDelay > 0)
   2164     {
   2165         //already delayed this frame, so render now.
   2166         iDelay = 0;
   2167     }
   2168     else //first call for this frame.
   2169     {
   2170         if (!iLastTimestampValid)
   2171         {
   2172             //this is the very first frame-- render it ASAP.
   2173             //render first frame ASAP.
   2174             iLastTimestampValid = true;
   2175             iDelay = 0;
   2176         }
   2177         else
   2178         {
   2179             //not the first frame.
   2180             //delay long enough to allow the prior data to render.
   2181             iDelay = aTs - iLastTimestamp;
   2182         }
   2183         //save this timestamp for next delta computation.
   2184         iLastTimestamp = aTs;
   2185     }
   2186 
   2187     //if delay is zero, it's time to render now.  in this case, we
   2188     //need to adjust the player clock with the device rendering time.
   2189     if (iDelay == 0)
   2190     {
   2191         AdjustClock(aTs);
   2192     }
   2193 
   2194     return iDelay;
   2195 }
   2196 
   2197 //
   2198 // Private section
   2199 //
   2200 PVMFStatus PVRefFileOutput::HandleReConfig(uint32 aReconfigSeqNum)
   2201 {
   2202     PVMFStatus status = PVMFFailure;
   2203     /* Close the existing file and open a new one */
   2204     if (iFileOpened)
   2205     {
   2206         iOutputFile.Close();
   2207     }
   2208     iFileOpened = false;
   2209 
   2210     aReconfigSeqNum++;
   2211     oscl_wchar append[8];
   2212     OSCL_wStackString<8> fmt(_STRLIT_WCHAR("%d"));
   2213     oscl_snprintf(append, 8, fmt.get_cstr(), aReconfigSeqNum);
   2214     append[7] = (oscl_wchar)'\0';
   2215     OSCL_wStackString<32> appendString(append);
   2216     iOutputFileName += appendString.get_cstr();
   2217     if (iOutputFile.Open(iOutputFileName.get_cstr(), Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY, iFs) == 0)
   2218     {
   2219         status = PVMFSuccess;
   2220         iFileOpened = true;
   2221         iParametersLogged = false;
   2222     }
   2223     return status;
   2224 }
   2225 
   2226 void PVRefFileOutput::Run()
   2227 {
   2228     //send async command responses
   2229     while (!iCommandResponseQueue.empty())
   2230     {
   2231         if (iObserver)
   2232         {
   2233             iObserver->RequestCompleted(PVMFCmdResp(iCommandResponseQueue[0].iCmdId, iCommandResponseQueue[0].iContext, iCommandResponseQueue[0].iStatus));
   2234         }
   2235         iCommandResponseQueue.erase(&iCommandResponseQueue[0]);
   2236     }
   2237 
   2238 
   2239     //send async write completion
   2240     while (!iWriteResponseQueue.empty())
   2241     {
   2242         //for active timing mode, insert some delays to simulate
   2243         //actual device rendering time.
   2244         if (!iWriteResponseQueue[0].iDiscard
   2245                 && iActiveTiming)
   2246         {
   2247             uint32 delay = iActiveTiming->GetDelayMsec(iWriteResponseQueue[0].iTimestamp);
   2248             if (delay > 0)
   2249             {
   2250                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
   2251                                 (0, "PVRefFileOutput::Run() Re-scheduling in %d msec", delay));
   2252                 RunIfNotReady(delay*1000);
   2253                 return;
   2254             }
   2255         }
   2256         //report write complete
   2257         if (iPeer)
   2258         {
   2259             iPeer->writeComplete(iWriteResponseQueue[0].iStatus, iWriteResponseQueue[0].iCmdId, (OsclAny*)iWriteResponseQueue[0].iContext);
   2260         }
   2261         //report playback position to the test observer.
   2262         if (iTestObserver)
   2263         {
   2264             iTestObserver->Pos(iWriteResponseQueue[0].iTimestamp);
   2265         }
   2266         iWriteResponseQueue.erase(&iWriteResponseQueue[0]);
   2267     }
   2268 
   2269     //Re-start the data transfer if needed.
   2270     if (iWriteBusy && iPeer)
   2271     {
   2272         iWriteBusy = false;
   2273         iPeer->statusUpdate(PVMI_MEDIAXFER_STATUS_WRITE);
   2274     }
   2275 }
   2276 
   2277 
   2278 int32 PVRefFileOutput::yuv2rgb(uint8 * pBufRGBRev, uint8 * pBufYUV, int32 width, int32 height)
   2279 {
   2280     int32 i, j, yi, yj;
   2281     int32 w2 = width / 2;
   2282     int32 rowoff, yrowoff, uvrowoff;
   2283     uint8 *pBufY = pBufYUV;
   2284     uint8 *pBufU = pBufYUV + width * height;
   2285     uint8 *pBufV = pBufU + width * height / 4;
   2286 
   2287     for (i = 0, yi = 0; i < height; i++, yi++)
   2288     {
   2289         rowoff = ((height - 1) - i) * width * 3;
   2290         yrowoff = yi * width;
   2291         uvrowoff = (yi / 2) * w2;
   2292         for (j = 0, yj = 0; j < width*3; j += 3, yj++)
   2293         {
   2294             pBufRGBRev[rowoff+j]   = (uint8)max(0, min(255, (1.164 * (pBufY[yrowoff+yj] - 16) +
   2295                                                 2.018 * (pBufU[uvrowoff+yj/2] - 128)))); // blue
   2296             pBufRGBRev[rowoff+j+1] = (uint8)max(0, min(255, (1.164 * (pBufY[yrowoff+yj] - 16) -
   2297                                                 0.813 * (pBufV[uvrowoff+yj/2] - 128) -
   2298                                                 0.391 * (pBufU[uvrowoff+yj/2] - 128)))); // green
   2299             pBufRGBRev[rowoff+j+2] = (uint8)max(0, min(255, (1.164 * (pBufY[yrowoff+yj] - 16) +
   2300                                                 1.596 * (pBufV[uvrowoff+yj/2] - 128)))); // red
   2301 
   2302         }
   2303     }
   2304     return 0;
   2305 }
   2306 
   2307 
   2308 void PVRefFileOutput::InitializeAVI(int width, int height)
   2309 {
   2310 
   2311     uint32 fsize, bsize;
   2312     fsize = width * height;          // avi physical frame size
   2313     bsize = width * height * 3;  // frame buffer size
   2314 
   2315     //Init the AVIMainHeader
   2316     iAVIMainHeader.dwMicroSecPerFrame = 200000;
   2317     iAVIMainHeader.dwMaxBytesPerSec    = 5 * 3 * width * height;
   2318     iAVIMainHeader.dwPaddingGranularity = 0;
   2319     iAVIMainHeader.dwFlags = AVIF_TRUSTCKTYPE_FILE_OUT | AVIF_HASINDEX_FILE_OUT;
   2320     iAVIMainHeader.dwTotalFrames = DEFAULT_COUNT;
   2321     iAVIMainHeader.dwInitialFrames = 0;
   2322     iAVIMainHeader.dwStreams = 1;
   2323     iAVIMainHeader.dwSuggestedBufferSize = bsize;
   2324     iAVIMainHeader.dwWidth = width;
   2325     iAVIMainHeader.dwHeight = height;
   2326     iAVIMainHeader.dwScale = 0;
   2327     iAVIMainHeader.dwRate = 0;
   2328     iAVIMainHeader.dwStart = 0;
   2329     iAVIMainHeader.dwLength = 0;
   2330 
   2331     // creating fourCC independent parameters
   2332     iAVIStreamHeader.fccType = streamtypeVIDEO;
   2333     /* support only YUV for now */
   2334     iAVIStreamHeader.fccHandler = mmioFOURCC('I', '4', '2', '0'); // BI_RGB
   2335     iAVIStreamHeader.dwFlags = 0;           // containing AVITF_ flags
   2336     iAVIStreamHeader.wPriority = 0;
   2337     iAVIStreamHeader.wLanguage = 0;
   2338     iAVIStreamHeader.dwScale = 1000;
   2339     iAVIStreamHeader.dwInitialFrames = 0;
   2340     iAVIStreamHeader.dwRate = 5000;
   2341     iAVIStreamHeader.dwStart = 0;
   2342     iAVIStreamHeader.dwLength = DEFAULT_COUNT;  /* will be changed later */
   2343     iAVIStreamHeader.dwSuggestedBufferSize = bsize;
   2344     iAVIStreamHeader.dwQuality = 0;
   2345     iAVIStreamHeader.dwSampleSize = 0;
   2346     iAVIStreamHeader.rcFrame.left = 0;
   2347     iAVIStreamHeader.rcFrame.top = 0;
   2348     iAVIStreamHeader.rcFrame.right = width;
   2349     iAVIStreamHeader.rcFrame.bottom = height;
   2350 
   2351     bi_hdr.biSize = sizeof(bi_hdr);
   2352     bi_hdr.biWidth = width;
   2353     bi_hdr.biHeight = height;
   2354     bi_hdr.biPlanes = 1;
   2355     bi_hdr.biXPelsPerMeter = 0;
   2356     bi_hdr.biYPelsPerMeter = 0;
   2357     bi_hdr.biClrUsed = 0;
   2358     bi_hdr.biClrImportant = 0;
   2359     bi_hdr.biBitCount = 24;             // every WORD a pixel
   2360     bi_hdr.biSizeImage = bsize;
   2361     bi_hdr.biCompression = iAVIStreamHeader.fccHandler;
   2362 }
   2363 
   2364 
   2365 void PVRefFileOutput::WriteHeaders()
   2366 {
   2367     if (iLogOutputToFile)
   2368     {
   2369 
   2370         uint32 tmp;
   2371 
   2372 #ifndef AVI_OUTPUT
   2373         return;
   2374 #endif
   2375 
   2376         tmp = FOURCC_RIFF;
   2377         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"RIFF"
   2378         tmp = 38016;
   2379         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte size til the end
   2380         tmp = formtypeAVI;
   2381         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"AVI "
   2382         tmp = FOURCC_LIST;
   2383         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"LIST"
   2384         tmp = 4 + 4 + 4 + sizeof(AVIMainHeader) + 4 + 4 + 4 + 4 + 4 + 4 + 4 + sizeof(AVIStreamHeader) + sizeof(BitMapInfoHeader);
   2385         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte list chunk size (entire list including all streams)
   2386 
   2387         // Write AVIMainHeader
   2388         tmp = listtypeAVIHEADER;
   2389         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"hdrl"
   2390         tmp = ckidAVIMAINHDR;
   2391         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"avih"
   2392         tmp = sizeof(AVIMainHeader);
   2393         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte AVI Header size
   2394         iAVIMainHeaderPosition = (TOsclFileOffsetInt32)iOutputFile.Tell();
   2395         iOutputFile.Write(&iAVIMainHeader, sizeof(uint8), sizeof(AVIMainHeader));  //AVI Header Data
   2396 
   2397         tmp = FOURCC_LIST;
   2398         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"LIST"
   2399         tmp = 4 + 4 + 4 + 4 + 4 + sizeof(AVIStreamHeader) + sizeof(BitMapInfoHeader);
   2400         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte size of second LIST chunk (for the first stream)
   2401         tmp = listtypeSTREAMHEADER;
   2402         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"strl"
   2403         tmp = ckidSTREAMHEADER;
   2404         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"strh"
   2405         tmp = sizeof(AVIStreamHeader);  //size of strh
   2406         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte size of strh
   2407 
   2408         iAVIStreamHeaderPosition = (TOsclFileOffsetInt32)iOutputFile.Tell();
   2409         iOutputFile.Write(&iAVIStreamHeader, sizeof(uint8), sizeof(AVIStreamHeader));
   2410 
   2411 
   2412         tmp = ckidSTREAMFORMAT;    //same format as BITMAPINFO
   2413         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"strf"
   2414         tmp = sizeof(BitMapInfoHeader);
   2415         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte size of  strf
   2416         iOutputFile.Write(&bi_hdr, sizeof(uint8), sizeof(BitMapInfoHeader));  //stream format data
   2417 
   2418         tmp = FOURCC_LIST;
   2419         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"LIST"
   2420         iVideoHeaderPosition = (TOsclFileOffsetInt32)iOutputFile.Tell();
   2421         tmp = 0;
   2422         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //4-byte size of movi chunk below
   2423         tmp = listtypeAVIMOVIE;
   2424         iOutputFile.Write(&tmp, sizeof(uint8), sizeof(uint32));  //"movi"
   2425     }
   2426 
   2427     uint32 tmp;
   2428     tmp = ckidAVINEWINDEX;
   2429     oscl_memcpy(&iIndexBuffer.indexBuffer[0], &tmp, sizeof(uint32));
   2430     iIndexBuffer.length = 4;
   2431     tmp = 0;
   2432     oscl_memcpy(&iIndexBuffer.indexBuffer[iIndexBuffer.length], &tmp, sizeof(uint32));
   2433     iIndexBuffer.length += 4;
   2434 }
   2435 
   2436 void PVRefFileOutput::AddChunk(uint8* chunk, uint32 size, uint32 ckid)
   2437 {
   2438     if (iLogOutputToFile)
   2439     {
   2440         iOutputFile.Write(&ckid, sizeof(uint8), sizeof(uint32));
   2441         iOutputFile.Write(&size, sizeof(uint8), sizeof(uint32));
   2442         iOutputFile.Write(chunk, sizeof(uint8), size);
   2443     }
   2444 
   2445     iAVIIndex.chunkID = videoChunkID;
   2446     iAVIIndex.flags = 0x10;
   2447     if (iVideoCount == 0)
   2448     {
   2449         iAVIIndex.offset = iIndexBuffer.length - 4;
   2450         iVideoCount++;
   2451         iPreviousOffset = iAVIIndex.offset;
   2452     }
   2453     else
   2454     {
   2455         iAVIIndex.offset = iPreviousOffset + size + 8;
   2456         iPreviousOffset = iAVIIndex.offset;
   2457 //      iAVIIndex.offset = 4 + (size + 8) * iVideoCount; //iIndexBuffer.length + size * iVideoCount;
   2458         iVideoCount++;
   2459     }
   2460     iAVIIndex.length = size;
   2461     oscl_memcpy(&iIndexBuffer.indexBuffer[iIndexBuffer.length], &iAVIIndex, sizeof(AVIIndex));
   2462     iIndexBuffer.length += sizeof(AVIIndex);
   2463 }
   2464 
   2465 void PVRefFileOutput::UpdateWaveChunkSize()
   2466 {
   2467     if (iLogOutputToFile)
   2468     {
   2469         int32 ret = (TOsclFileOffsetInt32)iOutputFile.Tell();
   2470         iOutputFile.Seek(4, Oscl_File::SEEKSET);
   2471         ret = (TOsclFileOffsetInt32)iOutputFile.Tell();
   2472     }
   2473     iRIFFChunk.chunkSize = 36 + iDataSubchunk.subchunk2Size;
   2474     if (iLogOutputToFile)
   2475     {
   2476         iOutputFile.Write(&iRIFFChunk.chunkSize, sizeof(uint8), 4);
   2477         iOutputFile.Seek(40, Oscl_File::SEEKSET);
   2478         iOutputFile.Write(&iDataSubchunk.subchunk2Size, sizeof(uint8), 4);
   2479         iOutputFile.Flush();
   2480     }
   2481 }
   2482 
   2483 void PVRefFileOutput::UpdateVideoChunkHeaderIdx()
   2484 {
   2485     //update the AVI Main Header
   2486     if (iVideoCount == 0 || iVideoLastTimeStamp == 0) return;
   2487     iAVIMainHeader.dwMicroSecPerFrame = (uint32)((float)iVideoLastTimeStamp / (float)iVideoCount * 1000);
   2488     iAVIMainHeader.dwMaxBytesPerSec    = (uint32)((float)(iVideoCount * 3 * iVideoHeight * iVideoWidth) / (float)iVideoLastTimeStamp * 1000);
   2489     iAVIMainHeader.dwTotalFrames = iVideoCount;
   2490 
   2491     if (iLogOutputToFile)
   2492     {
   2493         iOutputFile.Seek(iAVIMainHeaderPosition, Oscl_File::SEEKSET);
   2494         iOutputFile.Write(&iAVIMainHeader, sizeof(uint8), sizeof(AVIMainHeader));
   2495     }
   2496 
   2497     iAVIStreamHeader.dwRate = (uint32)((float)(iVideoCount * 1000000) / (float)iVideoLastTimeStamp);
   2498     iAVIStreamHeader.dwLength = iVideoCount;
   2499 
   2500     if (iLogOutputToFile)
   2501     {
   2502         iOutputFile.Seek(iAVIStreamHeaderPosition, Oscl_File::SEEKSET);
   2503         iOutputFile.Write(&iAVIStreamHeader, sizeof(uint8), sizeof(AVIStreamHeader));
   2504         iOutputFile.Seek(0, Oscl_File::SEEKEND);
   2505     }
   2506 
   2507     uint32 tmp = iIndexBuffer.length - 8;
   2508 
   2509     //write the indexBuffer to the file
   2510     oscl_memcpy(&iIndexBuffer.indexBuffer[4], &tmp, sizeof(uint32));
   2511     if (iLogOutputToFile)
   2512     {
   2513         iOutputFile.Write(iIndexBuffer.indexBuffer, sizeof(uint8), iIndexBuffer.length);
   2514         iOutputFile.Seek(0, Oscl_File::SEEKEND);
   2515     }
   2516     uint32 iAVISize = (TOsclFileOffsetInt32)iOutputFile.Tell() - 8;
   2517     if (iLogOutputToFile)
   2518     {
   2519         iOutputFile.Seek(4, Oscl_File::SEEKSET);
   2520         iOutputFile.Write(&iAVISize, sizeof(uint8), 4);
   2521         iOutputFile.Seek(iVideoHeaderPosition, Oscl_File::SEEKSET);
   2522     }
   2523     iAVIChunkSize += 4;
   2524     if (iLogOutputToFile)
   2525     {
   2526         iOutputFile.Write(&iAVIChunkSize, sizeof(uint8), 4);
   2527     }
   2528 }
   2529 
   2530 #if TEST_BUFFER_ALLOCATOR
   2531 
   2532 PVRefBufferAlloc::PVRefBufferAlloc(uint32 size, uint32 buffers): refCount(0), bufferSize(size), maxBuffers(buffers), numAllocated(0)
   2533 {
   2534 }
   2535 
   2536 PVRefBufferAlloc::~PVRefBufferAlloc()
   2537 {
   2538 
   2539 }
   2540 
   2541 void PVRefBufferAlloc::addRef()
   2542 {
   2543     ++refCount;
   2544 }
   2545 
   2546 void PVRefBufferAlloc::removeRef()
   2547 {
   2548     --refCount;
   2549     if (refCount <= 0)
   2550     {
   2551         this->~PVRefBufferAlloc();
   2552         OSCL_DELETE(this);
   2553     }
   2554 }
   2555 
   2556 
   2557 OsclAny* PVRefBufferAlloc::allocate()
   2558 {
   2559     if (numAllocated < maxBuffers)
   2560     {
   2561         OsclAny* ptr = oscl_malloc(bufferSize);
   2562         if (ptr) ++numAllocated;
   2563         return ptr;
   2564     }
   2565     return NULL;
   2566 }
   2567 
   2568 void PVRefBufferAlloc::deallocate(OsclAny* ptr)
   2569 {
   2570     if (ptr)
   2571     {
   2572         oscl_free(ptr);
   2573         --numAllocated;
   2574     }
   2575 }
   2576 
   2577 uint32 PVRefBufferAlloc::getBufferSize()
   2578 {
   2579     return bufferSize;
   2580 }
   2581 
   2582 uint32 PVRefBufferAlloc::getNumBuffers()
   2583 {
   2584     return maxBuffers;
   2585 }
   2586 
   2587 
   2588 bool PVRefBufferAlloc::queryInterface(const PVUuid& uuid, PVInterface*& aInterface)
   2589 {
   2590     aInterface = NULL; // initialize aInterface to NULL in case uuid is not supported
   2591 
   2592     if (PVMFFixedSizeBufferAllocUUID == uuid)
   2593     {
   2594         // Send back ptr to the allocator interface object
   2595         PVMFFixedSizeBufferAlloc* myInterface   = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, this);
   2596         refCount++; // increment interface refcount before returning ptr
   2597         aInterface = OSCL_STATIC_CAST(PVInterface*, myInterface);
   2598         return true;
   2599     }
   2600 
   2601     return false;
   2602 }
   2603 
   2604 #endif
   2605 
   2606