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