Home | History | Annotate | Download | only in include
      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 #ifndef PVMI_MEDIA_IO_FILEOUTPUT_H_INCLUDED
     19 #define PVMI_MEDIA_IO_FILEOUTPUT_H_INCLUDED
     20 
     21 #ifndef PVMI_MIO_CONTROL_H_INCLUDED
     22 #include "pvmi_mio_control.h"
     23 #endif
     24 #ifndef PVMI_MEDIA_TRANSFER_H_INCLUDED
     25 #include "pvmi_media_transfer.h"
     26 #endif
     27 #ifndef OSCL_SCHEDULER_AO_H_INCLUDED
     28 #include "oscl_scheduler_ao.h"
     29 #endif
     30 #ifndef PVMI_MEDIA_IO_OBSERVER_H_INCLUDED
     31 #include "pvmi_media_io_observer.h"
     32 #endif
     33 #ifndef OSCL_FILE_IO_H_INCLUDED
     34 #include "oscl_file_io.h"
     35 #endif
     36 #ifndef PVMI_CONFIG_AND_CAPABILITY_H_INCLUDED
     37 #include "pvmi_config_and_capability.h"
     38 #endif
     39 #ifndef OSCL_STRING_CONTAINERS_H_INCLUDED
     40 #include "oscl_string_containers.h"
     41 #endif
     42 #ifndef PVMI_MEDIA_IO_CLOCK_EXTENSION_H_INCLUDED
     43 #include "pvmi_media_io_clock_extension.h"
     44 #endif
     45 
     46 #ifndef AVI_WRITE_H_INCLUDED
     47 #include "avi_write.h"
     48 #endif
     49 
     50 #define TEST_BUFFER_ALLOCATOR 0
     51 
     52 #if TEST_BUFFER_ALLOCATOR
     53 #ifndef PV_INTERFACE_H
     54 #include "pv_interface.h"
     55 #endif
     56 
     57 #ifndef PVMF_FIXEDSIZE_BUFFER_ALLOC_H_INCLUDED
     58 #include "pvmf_fixedsize_buffer_alloc.h"
     59 #endif
     60 #endif
     61 
     62 class PVLogger;
     63 class PVRefFileOutputTestObserver;
     64 class PVMFMediaClock;
     65 class PVRefFileOutput;
     66 
     67 #define DEFAULT_NUM_DECODED_FRAMES_CAPABILITY   6
     68 
     69 // To maintain the count of supported uncompressed audio formats.
     70 // Should be updated whenever new format is added
     71 #define PVMF_SUPPORTED_UNCOMPRESSED_AUDIO_FORMATS_COUNT 6
     72 
     73 // To maintain the count of supported uncompressed video formats.
     74 // Should be updated whenever new format is added
     75 #define PVMF_SUPPORTED_UNCOMPRESSED_VIDEO_FORMATS_COUNT 6
     76 
     77 // To maintain the count of supported compressed audio formats.
     78 // Should be updated whenever new format is added
     79 #define PVMF_SUPPORTED_COMPRESSED_AUDIO_FORMATS_COUNT 18
     80 
     81 // To maintain the count of supported compressed video formats.
     82 // Should be updated whenever new format is added
     83 #define PVMF_SUPPORTED_COMPRESSED_VIDEO_FORMATS_COUNT 8
     84 
     85 #define PVMF_SUPPORTED_TEXT_FORMAT_COUNT 1
     86 
     87 
     88 
     89 
     90 typedef struct
     91 {
     92     uint32      chunkID;
     93     uint32      chunkSize;
     94     uint32      format;
     95 } RIFFChunk;
     96 
     97 typedef struct
     98 {
     99     uint32      subchunk1ID;
    100     uint32      subchunk1Size;
    101     uint16     audioFormat;
    102     uint16     numChannels;
    103     uint32      sampleRate;
    104     uint32      byteRate;
    105     uint16     blockAlign;
    106     uint16     bitsPerSample;
    107 } fmtSubchunk;
    108 
    109 typedef struct
    110 {
    111     uint32      subchunk2ID;
    112     uint32      subchunk2Size;
    113 } dataSubchunk;
    114 
    115 typedef enum
    116 {
    117     MEDIATYPE_VIDEO,
    118     MEDIATYPE_AUDIO,
    119     MEDIATYPE_TEXT,
    120     MEDIATYPE_UNKNOWN
    121 } MediaType;
    122 
    123 // A test feature for simulating a component with active timing.
    124 class PVRefFileOutputActiveTimingSupport: public PvmiClockExtensionInterface
    125 {
    126     public:
    127 
    128         PVRefFileOutputActiveTimingSupport(uint32 limit)
    129                 : iLastTimestampValid(false)
    130                 , iDelay(0)
    131                 , iQueueLimit(limit)
    132                 , iClock(NULL)
    133                 , iLogger(NULL)
    134         {}
    135         virtual ~PVRefFileOutputActiveTimingSupport()
    136         {}
    137 
    138         //from PvmiClockExtensionInterface
    139         OSCL_IMPORT_REF PVMFStatus SetClock(PVMFMediaClock *clockVal) ;
    140 
    141         //from PVInterface
    142         OSCL_IMPORT_REF void addRef() ;
    143         OSCL_IMPORT_REF void removeRef() ;
    144         OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid, PVInterface*& iface) ;
    145 
    146         void queryUuid(PVUuid& uuid);
    147 
    148         uint32 GetDelayMsec(PVMFTimestamp&);
    149         void AdjustClock(PVMFTimestamp& aTs);
    150 
    151         PVMFTimestamp iLastTimestamp;
    152         bool iLastTimestampValid;
    153         uint32 iDelay;
    154 
    155         uint32 iQueueLimit;
    156 
    157         PVMFMediaClock* iClock;
    158         PVLogger* iLogger;
    159 
    160         //query for whether playback clock is in frame-step mode.
    161         bool FrameStepMode();
    162 
    163 };
    164 
    165 
    166 // This class implements the reference media IO for file output.
    167 // This class constitutes the Media IO component
    168 
    169 class PVRefFileOutput : public OsclTimerObject
    170         , public PvmiMIOControl
    171         , public PvmiMediaTransfer
    172         , public PvmiCapabilityAndConfig
    173         , public PvmiClockExtensionInterface
    174 
    175 {
    176     public:
    177         OSCL_IMPORT_REF PVRefFileOutput(const oscl_wchar* aFileName,
    178                                         bool aActiveTiming = false);
    179 
    180         OSCL_IMPORT_REF PVRefFileOutput(const oscl_wchar* aFileName,
    181                                         MediaType aMediaType,
    182                                         bool aCompressedMedia = false);
    183 
    184         OSCL_IMPORT_REF PVRefFileOutput(const OSCL_wString& aFileName, bool logStrings = false);
    185 
    186         // Expanded constructor with test features.
    187         OSCL_IMPORT_REF PVRefFileOutput(const OSCL_wString& aFileName
    188                                         , PVRefFileOutputTestObserver*aObserver
    189                                         , bool aActiveTiming, uint32 aQueueLimit
    190                                         , bool aSimFlowControl
    191                                         , bool logStrings = true);
    192 
    193         ~PVRefFileOutput();
    194 
    195         // APIs from PvmiMIOControl
    196 
    197 
    198         PVMFStatus connect(PvmiMIOSession& aSession, PvmiMIOObserver* aObserver);
    199 
    200         PVMFStatus disconnect(PvmiMIOSession aSession);
    201 
    202         PVMFCommandId QueryUUID(const PvmfMimeString& aMimeType, Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
    203                                 bool aExactUuidsOnly = false, const OsclAny* aContext = NULL);
    204 
    205         PVMFCommandId QueryInterface(const PVUuid& aUuid, PVInterface*& aInterfacePtr, const OsclAny* aContext = NULL);
    206 
    207         PvmiMediaTransfer* createMediaTransfer(PvmiMIOSession& aSession, PvmiKvp* read_formats = NULL, int32 read_flags = 0,
    208                                                PvmiKvp* write_formats = NULL, int32 write_flags = 0);
    209 
    210         void deleteMediaTransfer(PvmiMIOSession& aSession, PvmiMediaTransfer* media_transfer);
    211 
    212         PVMFCommandId Init(const OsclAny* aContext = NULL);
    213 
    214         PVMFCommandId Reset(const OsclAny* aContext = NULL);
    215 
    216         PVMFCommandId Start(const OsclAny* aContext = NULL);
    217 
    218         PVMFCommandId Pause(const OsclAny* aContext = NULL);
    219 
    220         PVMFCommandId Flush(const OsclAny* aContext = NULL);
    221 
    222         PVMFCommandId DiscardData(const OsclAny* aContext = NULL);
    223 
    224         PVMFCommandId DiscardData(PVMFTimestamp aTimestamp, const OsclAny* aContext = NULL);
    225 
    226         PVMFCommandId Stop(const OsclAny* aContext = NULL);
    227 
    228         PVMFCommandId CancelAllCommands(const OsclAny* aContext = NULL);
    229 
    230         PVMFCommandId CancelCommand(PVMFCommandId aCmdId, const OsclAny* aContext = NULL);
    231 
    232         void ThreadLogon();
    233 
    234         void ThreadLogoff();
    235 
    236         // APIs from PvmiMediaTransfer
    237 
    238         void setPeer(PvmiMediaTransfer* aPeer);
    239 
    240         void useMemoryAllocators(OsclMemAllocator* write_alloc = NULL);
    241 
    242         PVMFCommandId writeAsync(uint8 format_type, int32 format_index,
    243                                  uint8* data, uint32 data_len,
    244                                  const PvmiMediaXferHeader& data_header_info,
    245                                  OsclAny* aContext = NULL);
    246 
    247         void writeComplete(PVMFStatus aStatus,
    248                            PVMFCommandId  write_cmd_id,
    249                            OsclAny* aContext);
    250 
    251         PVMFCommandId  readAsync(uint8* data, uint32 max_data_len,
    252                                  OsclAny* aContext = NULL,
    253                                  int32* formats = NULL, uint16 num_formats = 0);
    254 
    255         void readComplete(PVMFStatus aStatus, PVMFCommandId  read_cmd_id, int32 format_index,
    256                           const PvmiMediaXferHeader& data_header_info, OsclAny* aContext);
    257 
    258         void statusUpdate(uint32 status_flags);
    259 
    260         void cancelCommand(PVMFCommandId  command_id);
    261 
    262         void cancelAllCommands();
    263 
    264         void setUserClockExtnInterface(bool aEnable);
    265 
    266         // Pure virtuals from PvmiCapabilityAndConfig
    267 
    268         void setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver);
    269 
    270         PVMFStatus getParametersSync(PvmiMIOSession aSession, PvmiKeyType aIdentifier,
    271                                      PvmiKvp*& aParameters, int& num_parameter_elements, PvmiCapabilityContext aContext);
    272 
    273         PVMFStatus releaseParameters(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements);
    274 
    275         void createContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext);
    276 
    277         void setContextParameters(PvmiMIOSession aSession, PvmiCapabilityContext& aContext,
    278                                   PvmiKvp* aParameters, int num_parameter_elements);
    279 
    280         void DeleteContext(PvmiMIOSession aSession, PvmiCapabilityContext& aContext);
    281 
    282         void setParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters,
    283                                int num_elements, PvmiKvp * & aRet_kvp);
    284 
    285         PVMFCommandId setParametersAsync(PvmiMIOSession aSession, PvmiKvp* aParameters,
    286                                          int num_elements, PvmiKvp*& aRet_kvp, OsclAny* context = NULL);
    287 
    288         uint32 getCapabilityMetric(PvmiMIOSession aSession);
    289 
    290         PVMFStatus verifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements);
    291 
    292         void setFormatMask(uint32 mask);
    293 
    294         void UpdateWaveChunkSize();
    295 
    296         void WriteHeaders();
    297         void InitializeAVI(int width, int height);
    298         void AddChunk(uint8* chunk, uint32 size, uint32 ckid);
    299         int32 yuv2rgb(uint8 * pBufRGBRev, uint8 * pBufYUV, int32 width, int32 height);
    300         void UpdateVideoChunkHeaderIdx();
    301 
    302         //from PvmiClockExtensionInterface
    303         OSCL_IMPORT_REF PVMFStatus SetClock(PVMFMediaClock *clockVal) ;
    304 
    305         //from PVInterface
    306         OSCL_IMPORT_REF void addRef() ;
    307         OSCL_IMPORT_REF void removeRef() ;
    308         OSCL_IMPORT_REF bool queryInterface(const PVUuid& uuid, PVInterface*& iface) ;
    309         void queryUuid(PVUuid& uuid);
    310 
    311     private:
    312         void initData();
    313 
    314         // From OsclTimerObject
    315         void Run();
    316 
    317         void Reschedule();
    318 
    319         void Cleanup();
    320         void ResetData();
    321 
    322         PvmiMediaTransfer* iPeer;
    323 
    324         // The PvmiMIOControl class observer.
    325         PvmiMIOObserver* iObserver;
    326 
    327         //for generating command IDs
    328         uint32 iCommandCounter;
    329 
    330         //State
    331         enum PVRefFOState
    332         {
    333             STATE_IDLE
    334             , STATE_LOGGED_ON
    335             , STATE_INITIALIZED
    336             , STATE_STARTED
    337             , STATE_PAUSED
    338         };
    339         PVRefFOState iState;
    340 
    341         //Control command handling.
    342         class CommandResponse
    343         {
    344             public:
    345                 CommandResponse(PVMFStatus s, PVMFCommandId id, const OsclAny* ctx)
    346                         : iStatus(s), iCmdId(id), iContext(ctx)
    347                 {}
    348 
    349                 PVMFStatus iStatus;
    350                 PVMFCommandId iCmdId;
    351                 const OsclAny* iContext;
    352         };
    353         Oscl_Vector<CommandResponse, OsclMemAllocator> iCommandResponseQueue;
    354         void QueueCommandResponse(CommandResponse&);
    355 
    356         //Write command handling
    357         class WriteResponse
    358         {
    359             public:
    360                 WriteResponse(PVMFStatus s, PVMFCommandId id, const OsclAny* ctx, const PVMFTimestamp& ts, bool discard)
    361                         : iStatus(s), iCmdId(id), iContext(ctx), iTimestamp(ts), iDiscard(discard)
    362                 {}
    363 
    364                 PVMFStatus iStatus;
    365                 PVMFCommandId iCmdId;
    366                 const OsclAny* iContext;
    367                 PVMFTimestamp iTimestamp;
    368                 bool iDiscard;
    369         };
    370         Oscl_Vector<WriteResponse, OsclMemAllocator> iWriteResponseQueue;
    371 
    372         // Output file parameters
    373         OSCL_wHeapString<OsclMemAllocator> iOutputFileName;
    374         Oscl_FileServer iFs;
    375         bool iFsConnected;
    376         Oscl_File iOutputFile;
    377         bool iFileOpened;
    378 
    379         // Audio parameters.
    380         OSCL_HeapString<OsclMemAllocator> iAudioFormatString;
    381         PVMFFormatType iAudioFormat;
    382         int32 iAudioNumChannels;
    383         bool iAudioNumChannelsValid;
    384         int32 iAudioSamplingRate;
    385         bool iAudioSamplingRateValid;
    386 
    387         // Video parameters
    388         OSCL_HeapString<OsclMemAllocator> iVideoFormatString;
    389         PVMFFormatType iVideoFormat;
    390         int32 iVideoHeight;
    391         bool iVideoHeightValid;
    392         int32 iVideoWidth;
    393         bool iVideoWidthValid;
    394         int32 iVideoDisplayHeight;
    395         bool iVideoDisplayHeightValid;
    396         int32 iVideoDisplayWidth;
    397         bool iVideoDisplayWidthValid;
    398 
    399         int32 iNumberOfBuffers;
    400         int32 iBufferSize;
    401 
    402         // Text parameters
    403         OSCL_HeapString<OsclMemAllocator> iTextFormatString;
    404         PVMFFormatType iTextFormat;
    405 
    406         //For logging
    407         PVLogger* iLogger;
    408 
    409         //A switch for selecting whether to log some strings along
    410         //with the media data in the output file.
    411         bool iLogStrings;
    412         bool iParametersLogged;
    413         void LogParameters();
    414         void LogFrame(uint32 aSeqNum, const PVMFTimestamp& aTimestamp, uint32);
    415         void LogEndOfStream(uint32 aSeqNum, const PVMFTimestamp& aTimestamp);
    416         void LogCodecHeader(uint32 aSeqNum, const PVMFTimestamp& aTimestamp, uint32);
    417 
    418         //For implementing the write flow control
    419         bool iWriteBusy;
    420         uint32 iWriteBusySeqNum;
    421         bool CheckWriteBusy(uint32);
    422 
    423         //a test feature for testing flow control in the peer.
    424         bool iSimFlowControl;
    425 
    426         //a test observer class
    427         PVRefFileOutputTestObserver* iTestObserver;
    428 
    429         //a test feature for simulating active timing.
    430         PVRefFileOutputActiveTimingSupport* iActiveTiming;
    431 
    432         //a test feature to allow the commands such as GetCapability
    433         //to return a distinctive format type
    434         uint32 iFormatMask;
    435 
    436         //called when re-config notification is recvd
    437         PVMFStatus HandleReConfig(uint32 aReconfigSeqNum);
    438 
    439         //if iUseClockExtension set to true, no data is dropped
    440         bool iUseClockExtension;
    441 
    442         //Used for deciding when to send ConfigComplete event to MIO node
    443         bool iIsMIOConfigured;
    444 
    445         // used to create the WAV file output.
    446         RIFFChunk    iRIFFChunk;
    447         fmtSubchunk  iFmtSubchunk;
    448         dataSubchunk iDataSubchunk;
    449         bool         iHeaderWritten;
    450         PVMFTimestamp iVideoLastTimeStamp;
    451         bool         iInitializeAVIDone;
    452 
    453         AVIMainHeader iAVIMainHeader;
    454         AVIStreamHeader iAVIStreamHeader;
    455         BitMapInfoHeader bi_hdr;
    456         AVIIndex         iAVIIndex;
    457         uint32        iAVIChunkSize;
    458         uint32        iVideoHeaderPosition;
    459         IndexBuffer   iIndexBuffer;
    460         uint32        iAVIMainHeaderPosition;
    461         uint32        iAVIStreamHeaderPosition;
    462         uint32        iVideoCount;
    463         uint32        iPreviousOffset;
    464 
    465         MediaType     iMediaType;
    466         bool          iCompressedMedia;
    467         PVMFMediaClock* iClock;
    468         const bool iLogOutputToFile;
    469 };
    470 
    471 //An observer class for test support.
    472 class PVRefFileOutputTestObserver
    473 {
    474     public:
    475         virtual ~PVRefFileOutputTestObserver() {}
    476 
    477         OSCL_IMPORT_REF virtual void Pos(PVMFTimestamp& aTimestamp) = 0;
    478 };
    479 
    480 #if TEST_BUFFER_ALLOCATOR
    481 
    482 class PVRefBufferAlloc: public PVInterface, public PVMFFixedSizeBufferAlloc
    483 {
    484     public:
    485 
    486         PVRefBufferAlloc(uint32 size, uint32 buffers);
    487 
    488         virtual ~PVRefBufferAlloc();
    489 
    490         virtual void addRef();
    491 
    492         virtual void removeRef();
    493 
    494         virtual bool queryInterface(const PVUuid& uuid, PVInterface*& aInterface) ;
    495 
    496         virtual OsclAny* allocate();
    497 
    498         virtual void deallocate(OsclAny* ptr) ;
    499 
    500         virtual uint32 getBufferSize() ;
    501 
    502         virtual uint32 getNumBuffers() ;
    503 
    504     private:
    505         int32 refCount;
    506         int32 bufferSize;
    507         int32 maxBuffers;
    508         int32 numAllocated;
    509 };
    510 
    511 #endif
    512 
    513 #endif // PVMI_MEDIA_IO_FILEOUTPUT_H_INCLUDED
    514 
    515