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 PVRefFileOutputActiveTimingSupport(uint32 limit)128 PVRefFileOutputActiveTimingSupport(uint32 limit) 129 : iLastTimestampValid(false) 130 , iDelay(0) 131 , iQueueLimit(limit) 132 , iClock(NULL) 133 , iLogger(NULL) 134 {} ~PVRefFileOutputActiveTimingSupport()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: CommandResponse(PVMFStatus s,PVMFCommandId id,const OsclAny * ctx)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: WriteResponse(PVMFStatus s,PVMFCommandId id,const OsclAny * ctx,const PVMFTimestamp & ts,bool discard)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: ~PVRefFileOutputTestObserver()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