• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
OSCL_DLL_ENTRY_POINT_DEFAULT()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 
ReleaseMediaIO(PvmiMIOControl * aNode)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 
PVRefFileOutput(const OSCL_wString & aFileName,bool logStrings)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 
PVRefFileOutput(const OSCL_wString & aFileName,PVRefFileOutputTestObserver * aTestObs,bool aSimTiming,uint32 aQueueLimit,bool aSimFlowControl,bool logStrings)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 
PVRefFileOutput(const oscl_wchar * aFileName,bool aActiveTiming)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 
PVRefFileOutput(const oscl_wchar * aFileName,MediaType aMediaType,bool aCompressedMedia)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 
initData()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 
setUserClockExtnInterface(bool aEnable)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 
ResetData()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 
Cleanup()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 
~PVRefFileOutput()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 
connect(PvmiMIOSession & aSession,PvmiMIOObserver * aObserver)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 
disconnect(PvmiMIOSession aSession)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 
createMediaTransfer(PvmiMIOSession & aSession,PvmiKvp * read_formats,int32 read_flags,PvmiKvp * write_formats,int32 write_flags)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 
QueueCommandResponse(CommandResponse & aResp)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 
QueryUUID(const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)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 
QueryInterface(const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)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 
deleteMediaTransfer(PvmiMIOSession & aSession,PvmiMediaTransfer * media_transfer)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 
Init(const OsclAny * aContext)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 
Reset(const OsclAny * aContext)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 
Start(const OsclAny * aContext)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 
Pause(const OsclAny * aContext)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 
Flush(const OsclAny * aContext)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 
DiscardData(const OsclAny * aContext)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 
DiscardData(PVMFTimestamp aTimestamp,const OsclAny * aContext)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 
Stop(const OsclAny * aContext)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 
CancelAllCommands(const OsclAny * aContext)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 
CancelCommand(PVMFCommandId aCmdId,const OsclAny * aContext)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 
ThreadLogon()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 
ThreadLogoff()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 
setPeer(PvmiMediaTransfer * aPeer)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 
useMemoryAllocators(OsclMemAllocator * write_alloc)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 
CheckWriteBusy(uint32 aSeqNum)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 
LogParameters()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 
LogCodecHeader(uint32 aSeqNum,const PVMFTimestamp & aTimestamp,uint32 datalen)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 
LogEndOfStream(uint32 aSeqNum,const PVMFTimestamp & aTimestamp)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 
LogFrame(uint32 aSeqNum,const PVMFTimestamp & aTimestamp,uint32 datalen)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 
writeAsync(uint8 aFormatType,int32 aFormatIndex,uint8 * aData,uint32 aDataLen,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)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 
writeComplete(PVMFStatus aStatus,PVMFCommandId write_cmd_id,OsclAny * aContext)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 
readAsync(uint8 * data,uint32 max_data_len,OsclAny * aContext,int32 * formats,uint16 num_formats)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 
readComplete(PVMFStatus aStatus,PVMFCommandId read_cmd_id,int32 format_index,const PvmiMediaXferHeader & data_header_info,OsclAny * aContext)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 
statusUpdate(uint32 status_flags)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 
cancelCommand(PVMFCommandId command_id)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 
cancelAllCommands()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 
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)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 
getParametersSync(PvmiMIOSession aSession,PvmiKeyType aIdentifier,PvmiKvp * & aParameters,int & num_parameter_elements,PvmiCapabilityContext aContext)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 
releaseParameters(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)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 
createContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)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 
setContextParameters(PvmiMIOSession aSession,PvmiCapabilityContext & aContext,PvmiKvp * aParameters,int num_parameter_elements)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 
DeleteContext(PvmiMIOSession aSession,PvmiCapabilityContext & aContext)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 
setParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements,PvmiKvp * & aRet_kvp)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 
setParametersAsync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements,PvmiKvp * & aRet_kvp,OsclAny * context)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 
getCapabilityMetric(PvmiMIOSession aSession)1867 uint32 PVRefFileOutput::getCapabilityMetric(PvmiMIOSession aSession)
1868 {
1869     OSCL_UNUSED_ARG(aSession);
1870 
1871     return 0;
1872 }
1873 
verifyParametersSync(PvmiMIOSession aSession,PvmiKvp * aParameters,int num_elements)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 
setFormatMask(uint32 mask)2036 void PVRefFileOutput::setFormatMask(uint32 mask)
2037 {
2038     iFormatMask = mask;
2039 }
2040 
SetClock(PVMFMediaClock * clockVal)2041 OSCL_EXPORT_REF PVMFStatus PVRefFileOutput::SetClock(PVMFMediaClock *clockVal)
2042 {
2043     iClock = clockVal;
2044     return PVMFSuccess;
2045 }
2046 
addRef()2047 OSCL_EXPORT_REF void PVRefFileOutput::addRef()
2048 {
2049 }
2050 
removeRef()2051 OSCL_EXPORT_REF void PVRefFileOutput::removeRef()
2052 {
2053 }
2054 
queryInterface(const PVUuid & aUuid,PVInterface * & aInterface)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 }
queryUuid(PVUuid & uuid)2061 void PVRefFileOutput::queryUuid(PVUuid& uuid)
2062 {
2063     OSCL_UNUSED_ARG(uuid);
2064 }
2065 //
2066 // For active timing support
2067 //
SetClock(PVMFMediaClock * clockVal)2068 OSCL_EXPORT_REF PVMFStatus PVRefFileOutputActiveTimingSupport::SetClock(PVMFMediaClock *clockVal)
2069 {
2070     iClock = clockVal;
2071     return PVMFSuccess;
2072 }
2073 
addRef()2074 OSCL_EXPORT_REF void PVRefFileOutputActiveTimingSupport::addRef()
2075 {
2076 }
2077 
removeRef()2078 OSCL_EXPORT_REF void PVRefFileOutputActiveTimingSupport::removeRef()
2079 {
2080 }
2081 
queryInterface(const PVUuid & aUuid,PVInterface * & aInterface)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 
queryUuid(PVUuid & uuid)2096 void PVRefFileOutputActiveTimingSupport::queryUuid(PVUuid& uuid)
2097 {
2098     uuid = PvmiClockExtensionInterfaceUuid;
2099 }
2100 
FrameStepMode()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 
AdjustClock(PVMFTimestamp & aTs)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.
GetDelayMsec(PVMFTimestamp & aTs)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 //
HandleReConfig(uint32 aReconfigSeqNum)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 
Run()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 
yuv2rgb(uint8 * pBufRGBRev,uint8 * pBufYUV,int32 width,int32 height)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 
InitializeAVI(int width,int height)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 
WriteHeaders()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 
AddChunk(uint8 * chunk,uint32 size,uint32 ckid)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 
UpdateWaveChunkSize()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 
UpdateVideoChunkHeaderIdx()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 
PVRefBufferAlloc(uint32 size,uint32 buffers)2532 PVRefBufferAlloc::PVRefBufferAlloc(uint32 size, uint32 buffers): refCount(0), bufferSize(size), maxBuffers(buffers), numAllocated(0)
2533 {
2534 }
2535 
~PVRefBufferAlloc()2536 PVRefBufferAlloc::~PVRefBufferAlloc()
2537 {
2538 
2539 }
2540 
addRef()2541 void PVRefBufferAlloc::addRef()
2542 {
2543     ++refCount;
2544 }
2545 
removeRef()2546 void PVRefBufferAlloc::removeRef()
2547 {
2548     --refCount;
2549     if (refCount <= 0)
2550     {
2551         this->~PVRefBufferAlloc();
2552         OSCL_DELETE(this);
2553     }
2554 }
2555 
2556 
allocate()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 
deallocate(OsclAny * ptr)2568 void PVRefBufferAlloc::deallocate(OsclAny* ptr)
2569 {
2570     if (ptr)
2571     {
2572         oscl_free(ptr);
2573         --numAllocated;
2574     }
2575 }
2576 
getBufferSize()2577 uint32 PVRefBufferAlloc::getBufferSize()
2578 {
2579     return bufferSize;
2580 }
2581 
getNumBuffers()2582 uint32 PVRefBufferAlloc::getNumBuffers()
2583 {
2584     return maxBuffers;
2585 }
2586 
2587 
queryInterface(const PVUuid & uuid,PVInterface * & aInterface)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