• 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 /**
19  * @file pvmp4ffcn_node.cpp
20  * @brief Node for PV MPEG4 file format composer
21  */
22 #undef ANDROID
23 #ifdef ANDROID
24 // #define LOG_NDEBUG 0
25 #define LOG_TAG "PvMp4Composer"
26 #include <utils/Log.h>
27 #include <utils/Errors.h>
28 #include <utils/threads.h>
29 #endif // ANDROID
30 
31 #ifndef PVMP4FFCN_NODE_H_INCLUDED
32 #include "pvmp4ffcn_node.h"
33 #endif
34 #ifndef PVMP4FFCN_FACTORY_H_INCLUDED
35 #include "pvmp4ffcn_factory.h"
36 #endif
37 #ifndef PVMP4FFCN_PORT_H_INCLUDED
38 #include "pvmp4ffcn_port.h"
39 #endif
40 #ifndef OSCL_DLL_H_INCLUDED
41 #include "oscl_dll.h"
42 #endif
43 #ifndef OSCL_MEM_BASIC_FUNCTIONS_H
44 #include "oscl_mem_basic_functions.h"
45 #endif
46 #include "pvmf_omx_basedec_node.h"  // for NUMBER_OUTPUT_BUFFER
47 
48 #ifdef ANDROID
49 namespace android
50 {
51 
52 // FragmentWriter is a queue of media fragment to be written in the
53 // media file. The caller enqueues the next fragment and returns
54 // immediately. An separate thread dequeues the fragment and writes it.
55 //
56 // This class is friend with the composer node it belongs to, in order
57 // to be able to call the original AddMemFragToTrack which does all
58 // the work.
59 //
60 // The queue is implemented using a circular buffer. mBuffer is the
61 // start of the array and mEnd points just after the last element in
62 // the array.
63 // mFirst points to the oldest fragment.
64 // mLast points to the next available cell for a new fragment.
65 // When the array is empty or full mFirst == mLast.
66 
67 class FragmentWriter: public Thread
68 {
69     public:
FragmentWriter(PVMp4FFComposerNode * composer)70         FragmentWriter(PVMp4FFComposerNode *composer) :
71                 Thread(kThreadCallJava), mSize(0), mEnd(mBuffer + kCapacity),
72                 mFirst(mBuffer), mLast(mBuffer), mComposer(composer),
73                 mPrevWriteStatus(PVMFPending), mTid(NULL), mDropped(0), mExitRequested(false) {}
74 
~FragmentWriter()75         virtual ~FragmentWriter()
76         {
77             Mutex::Autolock l(mRequestMutex);
78             LOG_ASSERT(0 == mSize, "The queue should be empty by now.");
79             LOG_ASSERT(mExitRequested, "Deleting an active instance.");
80             LOGD_IF(0 < mSize, "Flushing %d frags in dtor", mSize);
81             while (0 < mSize)  // make sure we are flushed
82             {
83                 decrPendingRequests();
84             }
85         }
86 
87         // Mark the thread as exiting and kick it so it can see the
88         // exitPending state.
requestExit()89         virtual void requestExit()
90         {
91             mExitRequested = true;
92             Thread::requestExit();
93             mRequestMutex.lock();
94             mRequestCv.signal();
95             mRequestMutex.unlock();
96         }
97 
98         // Wait for all the fragment to be written.
flush()99         virtual void flush()
100         {
101             LOG_ASSERT(androidGetThreadId() != mTid, "Reentrant call");
102 
103             bool done = false;
104             size_t iter = 0;
105             while (!done)
106             {
107                 mRequestMutex.lock();
108                 done = mSize == 0 || iter > kMaxFlushAttempts;
109                 if (!done) mRequestCv.signal();
110                 mRequestMutex.unlock();
111                 if (!done) usleep(kFlushSleepMicros);
112                 ++iter;
113             }
114             LOG_ASSERT(iter <= kMaxFlushAttempts, "Failed to flush");
115         }
116 
117         // Called by the ProcessIncomingMsg method from the
118         // PVMp4FFComposerNode to append the fragment to the track.
119         // @return The result of the *previous* fragment written. Since the call
120         //         is asynch we cannot wait.
enqueueMemFragToTrack(Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> aFrame,OsclRefCounterMemFrag & aMemFrag,PVMFFormatType aFormat,uint32 & aTimestamp,int32 aTrackId,PVMp4FFComposerPort * aPort)121         PVMFStatus enqueueMemFragToTrack(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame,
122                                          OsclRefCounterMemFrag& aMemFrag, PVMFFormatType aFormat,
123                                          uint32& aTimestamp, int32 aTrackId, PVMp4FFComposerPort *aPort)
124         {
125             if (mExitRequested) return PVMFErrCancelled;
126             Mutex::Autolock lock(mRequestMutex);
127 
128             // When the queue is full, we drop the request. This frees the
129             // memory fragment and keeps the system running. Decoders are
130             // unhappy when there is no buffer available to write the
131             // output.
132             // An alternative would be to discard the oldest fragment
133             // enqueued to free some space. However that would modify
134             // mFirst and require extra locking because the thread maybe
135             // in the process of writing it.
136             if (mSize == kCapacity)
137             {
138                 ++mDropped;
139                 LOGW_IF((mDropped % kLogDroppedPeriod) == 0, "Frame %d dropped.", mDropped);
140                 // TODO: Should we return an error code here?
141                 return mPrevWriteStatus;
142             }
143 
144             mLast->set(aFrame, aMemFrag, aFormat, aTimestamp, aTrackId, aPort);
145             incrPendingRequests();
146 
147             mRequestCv.signal();
148             return mPrevWriteStatus;
149         }
150 
151     private:
152         static const bool kThreadCallJava = false;
153         static const size_t kLogDroppedPeriod = 10;  // Arbitrary.
154         // Must match the number of buffers allocated in the decoder.
155         static const size_t kCapacity = NUMBER_OUTPUT_BUFFER;
156         static const size_t kWarningThreshold = kCapacity * 3 / 4; // Warn at 75%
157         static const OsclRefCounterMemFrag kEmptyFrag;
158         // Flush blocks for 2 seconds max.
159         static const size_t kMaxFlushAttempts = 10;
160         static const int kFlushSleepMicros = 200 * 1000;
161 
162         struct Request
163         {
setandroid::FragmentWriter::Request164             void set(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame,
165                      OsclRefCounterMemFrag& aMemFrag, PVMFFormatType aFormat,
166                      uint32 aTimestamp, int32 aTrackId, PVMp4FFComposerPort *aPort)
167             {
168                 mFrame = aFrame;
169                 mFrag = aMemFrag;
170                 mFormat = aFormat;
171                 mTimestamp = aTimestamp;
172                 mTrackId = aTrackId;
173                 mPort = aPort;
174             }
175 
176             Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> mFrame;
177             OsclRefCounterMemFrag mFrag;
178             PVMFFormatType mFormat;
179             uint32 mTimestamp;
180             uint32 mTrackId;
181             PVMp4FFComposerPort *mPort;
182         };
183 
incrPendingRequests()184         void incrPendingRequests()
185         {
186             ++mLast;
187             if (mEnd == mLast) mLast = mBuffer;
188             ++mSize;
189         }
190 
decrPendingRequests()191         void decrPendingRequests()
192         {
193             mFirst->mFrame.clear();
194             // Release the memory fragment tracked using a refcount
195             // class. Need to assign an empty frag to release the memory
196             // fragment. We cannot wait for the array to wrap around.
197             mFirst->mFrag = kEmptyFrag;  // FIXME: This assignement to decr the ref count is ugly.
198             ++mFirst;
199             if (mEnd == mFirst) mFirst = mBuffer;
200             --mSize;
201         }
202 
203         // Called by the base class Thread.
204         // @return true if there more work to do. false when done.
205         // @Override Thread
threadLoop()206         virtual bool threadLoop()
207         {
208             if (!mTid) mTid = androidGetThreadId();
209 
210             LOG_ASSERT(androidGetThreadId() == mTid,
211                        "Thread id has changed!: %p != %p", mTid, androidGetThreadId());
212 
213             size_t numFrags = 0;
214             // Check if there's work to do. Otherwise wait for new fragment.
215             mRequestMutex.lock();
216             numFrags = mSize;
217             mRequestMutex.unlock();
218 
219             bool doneWaiting = numFrags != 0;
220             while (!doneWaiting)
221             {
222                 mRequestMutex.lock();
223                 mRequestCv.wait(mRequestMutex);
224                 doneWaiting = mSize > 0 || mExitRequested;
225                 numFrags = mSize;
226                 mRequestMutex.unlock();
227             }
228 
229             if (mExitRequested) return false;
230 
231             LOGW_IF(numFrags > kWarningThreshold, "%d fragments in queue.", numFrags);
232             for (size_t i = 0; i < numFrags; ++i)
233             {
234                 // Don't lock the array while we are calling
235                 // AddMemFragToTrack, which may last a long time, because
236                 // we are the only thread accessing mFirst.
237                 mPrevWriteStatus = mComposer->AddMemFragToTrack(
238                                        mFirst->mFrame, mFirst->mFrag, mFirst->mFormat,
239                                        mFirst->mTimestamp, mFirst->mTrackId, mFirst->mPort);
240 
241                 mRequestMutex.lock();
242                 decrPendingRequests();
243                 mRequestMutex.unlock();
244             }
245             return true;
246         }
247 
248 
249         Mutex mRequestMutex;  // Protects mRequestCv, mBuffer, mFirst, mLast, mDropped
250         Condition mRequestCv;
251         Request mBuffer[kCapacity];
252         size_t mSize;
253         void *const mEnd;  // Marker for the end of the array.
254         Request *mFirst, *mLast;
255 
256         // mComposer with the real implementation of the AddMemFragToTrack method.
257         PVMp4FFComposerNode *mComposer;
258         // TODO: lock needed for mPrevWriteStatus? Are int assignement atomic on arm?
259         PVMFStatus mPrevWriteStatus;
260 
261         android_thread_id_t mTid;
262         size_t mDropped;
263         // Unlike exitPending(), stays to true once exit has been called.
264         bool mExitRequested;
265 };
266 const OsclRefCounterMemFrag FragmentWriter::kEmptyFrag;
267 }
268 #endif // ANDROID
269 
270 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m);
271 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m);
272 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
273 #define LOGDATATRAFFIC(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_INFO,m);
274 
275 #ifdef _TEST_AE_ERROR_HANDLING
276 const uint32 FAIL_NODE_CMD_START = 2;
277 const uint32 FAIL_NODE_CMD_STOP = 3;
278 const uint32 FAIL_NODE_CMD_FLUSH = 4;
279 const uint32 FAIL_NODE_CMD_PAUSE = 5;
280 const uint32 FAIL_NODE_CMD_RELEASE_PORT = 7;
281 #endif
282 
283 #define SLASH '/'
284 
285 #define LANG_CODE_SIZE 3
286 
287 // Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()288 OSCL_DLL_ENTRY_POINT_DEFAULT()
289 
290 
291 
292 ////////////////////////////////////////////////////////////////////////////
293 OSCL_EXPORT_REF PVMFNodeInterface* PVMp4FFComposerNodeFactory::CreateMp4FFComposer(int32 aPriority)
294 {
295     int32 err = 0;
296     PVMFNodeInterface* node = NULL;
297 
298     OSCL_TRY(err,
299              node = (PVMFNodeInterface*)OSCL_NEW(PVMp4FFComposerNode, (aPriority));
300              if (!node)
301              OSCL_LEAVE(OsclErrNoMemory);
302             );
303 
304     OSCL_FIRST_CATCH_ANY(err, return NULL;);
305     return node;
306 }
307 
308 ////////////////////////////////////////////////////////////////////////////
DeleteMp4FFComposer(PVMFNodeInterface * aComposer)309 OSCL_EXPORT_REF bool PVMp4FFComposerNodeFactory::DeleteMp4FFComposer(PVMFNodeInterface* aComposer)
310 {
311     if (aComposer)
312     {
313         PVMp4FFComposerNode* node = (PVMp4FFComposerNode*)aComposer;
314         OSCL_DELETE(node);
315         return true;
316     }
317 
318     return false;
319 }
320 
321 ////////////////////////////////////////////////////////////////////////////
PVMp4FFComposerNode(int32 aPriority)322 PVMp4FFComposerNode::PVMp4FFComposerNode(int32 aPriority)
323         : OsclActiveObject(aPriority, "PVMp4FFComposerNode")
324         , iMpeg4File(NULL)
325         , iFileType(0)
326         , iAuthoringMode(PVMP4FF_3GPP_DOWNLOAD_MODE)
327         , iPresentationTimescale(1000)
328         , iMovieFragmentDuration(2000)
329         , iRecordingYear(0)
330         , iClockConverter(8000)
331         , iExtensionRefCount(0)
332         , iRealTimeTS(false)
333         , iInitTSOffset(false)
334         , iTSOffset(0)
335         , iMaxFileSizeEnabled(false)
336         , iMaxDurationEnabled(false)
337         , iMaxFileSize(0)
338         , iMaxTimeDuration(0)
339         , iFileSizeReportEnabled(false)
340         , iDurationReportEnabled(false)
341         , iFileSizeReportFreq(0)
342         , iDurationReportFreq(0)
343         , iNextDurationReport(0)
344         , iNextFileSizeReport(0)
345         , iCacheSize(0)
346         , iConfigSize(0)
347         , pConfig(NULL)
348         , iTrackId_H264(0)
349         , iTrackId_Text(0)
350         , iSyncSample(0)
351         , iformat_h264(PVMF_MIME_FORMAT_UNKNOWN)
352         , iformat_text(PVMF_MIME_FORMAT_UNKNOWN)
353         , iNodeEndOfDataReached(false)
354         , iSampleInTrack(false)
355         , iFileRendered(false)
356 {
357     iInterfaceState = EPVMFNodeCreated;
358     iNum_PPS_Set = 0;
359     iNum_SPS_Set = 0;
360     iText_sdIndex = 0;
361     iFileObject = NULL;
362 #if PROFILING_ON
363     iMaxSampleAddTime = 0;
364     iMinSampleAddTime = 0;
365     iMinSampleSize = 0;
366     iMaxSampleSize = 0;
367     iNumSamplesAdded = 0;
368     oDiagnosticsLogged = false;
369     iDiagnosticsLogger = PVLogger::GetLoggerObject("pvauthordiagnostics.composer.mp4");
370     // Statistics
371     for (uint32 i = 0; i < 3; i++)
372         oscl_memset(&(iStats[i]), 0, sizeof(PVMp4FFCNStats));
373 #endif
374 
375     iLogger = PVLogger::GetLoggerObject("PVMp4FFComposerNode");
376     iDataPathLogger = PVLogger::GetLoggerObject("datapath.sinknode.mp4composer");
377     int32 err;
378     OSCL_TRY(err,
379              //Create the input command queue.  Use a reserve to avoid lots of
380              //dynamic memory allocation.
381              iCmdQueue.Construct(PVMF_MP4FFCN_COMMAND_ID_START, PVMF_MP4FFCN_COMMAND_VECTOR_RESERVE);
382              iCurrentCmd.Construct(0, 1); // There's only 1 current command
383 
384 
385              //Create the port vector.
386              iInPorts.Construct(PVMF_MP4FFCN_PORT_VECTOR_RESERVE);
387             );
388 
389     OSCL_FIRST_CATCH_ANY(err,
390                          //if a leave happened, cleanup and re-throw the error
391                          iCmdQueue.clear();
392                          iCurrentCmd.clear();
393                          iInPorts.clear();
394                          memvector_sps.clear();
395                          memvector_pps.clear();
396                          OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
397                          OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
398                          OSCL_LEAVE(err);
399                         );
400 
401 #ifdef ANDROID
402     iMaxReachedEvent = 0;
403     iMaxReachedReported = false;
404     iFragmentWriter = new android::FragmentWriter(this);
405     iFragmentWriter->run(LOG_TAG);
406 #endif
407 
408 #ifdef _TEST_AE_ERROR_HANDLING
409     iErrorHandlingAddMemFrag = false;
410     iErrorHandlingAddTrack = false;
411     iErrorCreateComposer = false;
412     iErrorRenderToFile = false;
413     iErrorAddTrack = PVMF_MIME_FORMAT_UNKNOWN;
414     iErrorNodeCmd = 0;
415     iTestFileSize = 0;
416     iTestTimeStamp = 0;
417     iErrorAddSample = 0;
418     iFileSize = 0;
419     iFileDuration = 0;
420     iErrorDataPathStall = 0;
421 #endif
422 }
423 
424 ////////////////////////////////////////////////////////////////////////////
~PVMp4FFComposerNode()425 PVMp4FFComposerNode::~PVMp4FFComposerNode()
426 {
427 #if PROFILING_ON
428     if (!oDiagnosticsLogged)
429     {
430         LogDiagnostics();
431     }
432 #endif
433 
434 #ifdef ANDROID
435     if (iFragmentWriter != NULL)
436     {
437         iFragmentWriter->requestExit(); // kick the thread
438         iFragmentWriter->requestExitAndWait();
439     }
440 #endif
441 
442     if (iMpeg4File)
443     {
444         PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
445 
446         if (!iFileRendered)
447         {
448             iFs.Connect();
449             iFs.Oscl_DeleteFile(iFileName.get_cstr());
450             iFs.Close();
451         }
452     }
453     if (iFileObject)
454     {
455         iFileObject->Close();
456         OSCL_DELETE(iFileObject);
457         iFileObject = NULL;
458     }
459     for (uint32 i = 0; i < iKeyWordVector.size() ; i++)
460     {
461         if (iKeyWordVector[i] != NULL)
462         {
463             OSCL_DELETE(iKeyWordVector[i]);
464             iKeyWordVector[i] = NULL;
465         }
466 
467     }
468 
469     if (pConfig != NULL)
470     {
471         OSCL_FREE(pConfig);
472         iConfigSize = 0;
473     }
474 
475     if (iLocationInfo._location_name != NULL)
476     {
477         OSCL_FREE(iLocationInfo._location_name);
478     }
479 
480     if (iLocationInfo._astronomical_body != NULL)
481     {
482         OSCL_FREE(iLocationInfo._astronomical_body);
483     }
484 
485     if (iLocationInfo._additional_notes != NULL)
486     {
487         OSCL_FREE(iLocationInfo._additional_notes);
488     }
489     // Cleanup allocated ports
490     while (!iInPorts.empty())
491     {
492         iInPorts.Erase(&iInPorts.front());
493 
494     }
495     //Cleanup commands
496     //The command queues are self-deleting, but we want to
497     //notify the observer of unprocessed commands.
498     while (!iCmdQueue.empty())
499     {
500         CommandComplete(iCmdQueue, iCmdQueue[0], PVMFFailure);
501     }
502 
503     while (!iCurrentCmd.empty())
504     {
505         CommandComplete(iCurrentCmd, iCurrentCmd[0], PVMFFailure);
506     }
507     iNodeEndOfDataReached = false;
508 
509     Cancel();
510     if (iInterfaceState != EPVMFNodeCreated)
511         iInterfaceState = EPVMFNodeIdle;
512 
513 }
514 
515 ////////////////////////////////////////////////////////////////////////////
ThreadLogon()516 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::ThreadLogon()
517 {
518     switch (iInterfaceState)
519     {
520         case EPVMFNodeCreated:
521             if (!IsAdded())
522                 AddToScheduler();
523             SetState(EPVMFNodeIdle);
524             return PVMFSuccess;
525         default:
526             return PVMFErrInvalidState;
527     }
528 }
529 
530 ////////////////////////////////////////////////////////////////////////////
ThreadLogoff()531 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::ThreadLogoff()
532 {
533     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMp4FFComposerNode:ThreadLogoff"));
534     switch (iInterfaceState)
535     {
536         case EPVMFNodeIdle:
537             if (IsAdded())
538                 RemoveFromScheduler();
539             iLogger = NULL;
540             iDataPathLogger = NULL;
541             SetState(EPVMFNodeCreated);
542             return PVMFSuccess;
543 
544         default:
545             return PVMFErrInvalidState;
546     }
547 }
548 
549 ////////////////////////////////////////////////////////////////////////////
GetCapability(PVMFNodeCapability & aNodeCapability)550 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::GetCapability(PVMFNodeCapability& aNodeCapability)
551 {
552     aNodeCapability.iCanSupportMultipleInputPorts = true;
553     aNodeCapability.iCanSupportMultipleOutputPorts = false;
554     aNodeCapability.iHasMaxNumberOfPorts = true;
555     aNodeCapability.iMaxNumberOfPorts = PVMF_MP4FFCN_MAX_INPUT_PORT + PVMF_MP4FFCN_MAX_OUTPUT_PORT;
556     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_M4V);
557     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_MP4);
558     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H2631998);
559     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H2632000);
560     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IETF);
561     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF);
562     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_3GPP_TIMEDTEXT);
563     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO);
564     return PVMFSuccess;
565 }
566 
567 ////////////////////////////////////////////////////////////////////////////
GetPorts(const PVMFPortFilter * aFilter)568 OSCL_EXPORT_REF PVMFPortIter* PVMp4FFComposerNode::GetPorts(const PVMFPortFilter* aFilter)
569 {
570     OSCL_UNUSED_ARG(aFilter);
571     iInPorts.Reset();
572     return &iInPorts;
573 }
574 
575 ////////////////////////////////////////////////////////////////////////////
QueryUUID(PVMFSessionId aSession,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)576 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::QueryUUID(PVMFSessionId aSession, const PvmfMimeString& aMimeType,
577         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
578         bool aExactUuidsOnly, const OsclAny* aContext)
579 {
580     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::QueryUUID"));
581 
582     PVMp4FFCNCmd cmd;
583     cmd.Construct(aSession, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
584     return QueueCommandL(cmd);
585 }
586 
587 ////////////////////////////////////////////////////////////////////////////
QueryInterface(PVMFSessionId aSession,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)588 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::QueryInterface(PVMFSessionId aSession, const PVUuid& aUuid,
589         PVInterface*& aInterfacePtr,
590         const OsclAny* aContext)
591 {
592     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
593                     (0, "PVMp4FFComposerNode::QueryInterface"));
594     PVMp4FFCNCmd cmd;
595     cmd.Construct(aSession, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
596     return QueueCommandL(cmd);
597 }
598 
599 ////////////////////////////////////////////////////////////////////////////
Init(PVMFSessionId aSession,const OsclAny * aContext)600 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Init(PVMFSessionId aSession, const OsclAny* aContext)
601 {
602     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Init"));
603     PVMp4FFCNCmd cmd;
604     cmd.Construct(aSession, PVMF_GENERIC_NODE_INIT, aContext);
605     return QueueCommandL(cmd);
606 }
607 
608 ////////////////////////////////////////////////////////////////////////////
Prepare(PVMFSessionId aSession,const OsclAny * aContext)609 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Prepare(PVMFSessionId aSession, const OsclAny* aContext)
610 {
611     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Prepare"));
612     PVMp4FFCNCmd cmd;
613     cmd.Construct(aSession, PVMF_GENERIC_NODE_PREPARE, aContext);
614     return QueueCommandL(cmd);
615 }
616 
617 ////////////////////////////////////////////////////////////////////////////
RequestPort(PVMFSessionId aSession,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)618 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::RequestPort(PVMFSessionId aSession,
619         int32 aPortTag,
620         const PvmfMimeString* aPortConfig,
621         const OsclAny* aContext)
622 {
623     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::RequestPort"));
624     PVMp4FFCNCmd cmd;
625     cmd.Construct(aSession, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
626     return QueueCommandL(cmd);
627 }
628 
629 ////////////////////////////////////////////////////////////////////////////
ReleasePort(PVMFSessionId aSession,PVMFPortInterface & aPort,const OsclAny * aContext)630 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::ReleasePort(PVMFSessionId aSession,
631         PVMFPortInterface& aPort,
632         const OsclAny* aContext)
633 {
634     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::ReleasePort"));
635     PVMp4FFCNCmd cmd;
636     cmd.Construct(aSession, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
637     return QueueCommandL(cmd);
638 }
639 
640 ////////////////////////////////////////////////////////////////////////////
Start(PVMFSessionId aSession,const OsclAny * aContext)641 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Start(PVMFSessionId aSession, const OsclAny* aContext)
642 {
643     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Start"));
644     PVMp4FFCNCmd cmd;
645     cmd.Construct(aSession, PVMF_GENERIC_NODE_START, aContext);
646     return QueueCommandL(cmd);
647 }
648 
649 ////////////////////////////////////////////////////////////////////////////
Stop(PVMFSessionId aSession,const OsclAny * aContext)650 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Stop(PVMFSessionId aSession, const OsclAny* aContext)
651 {
652     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Stop"));
653     PVMp4FFCNCmd cmd;
654     cmd.Construct(aSession, PVMF_GENERIC_NODE_STOP, aContext);
655     return QueueCommandL(cmd);
656 }
657 
658 ////////////////////////////////////////////////////////////////////////////
Pause(PVMFSessionId aSession,const OsclAny * aContext)659 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Pause(PVMFSessionId aSession, const OsclAny* aContext)
660 {
661     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Pause"));
662     PVMp4FFCNCmd cmd;
663     cmd.Construct(aSession, PVMF_GENERIC_NODE_PAUSE, aContext);
664     return QueueCommandL(cmd);
665 }
666 
Flush(PVMFSessionId aSession,const OsclAny * aContext)667 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Flush(PVMFSessionId aSession, const OsclAny* aContext)
668 {
669     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Flush"));
670     PVMp4FFCNCmd cmd;
671     cmd.Construct(aSession, PVMF_GENERIC_NODE_FLUSH, aContext);
672     return QueueCommandL(cmd);
673 }
674 
675 ////////////////////////////////////////////////////////////////////////////
Reset(PVMFSessionId aSession,const OsclAny * aContext)676 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Reset(PVMFSessionId aSession, const OsclAny* aContext)
677 {
678     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Reset"));
679     PVMp4FFCNCmd cmd;
680     cmd.Construct(aSession, PVMF_GENERIC_NODE_RESET, aContext);
681     return QueueCommandL(cmd);
682 }
683 
684 ////////////////////////////////////////////////////////////////////////////
CancelAllCommands(PVMFSessionId aSession,const OsclAny * aContext)685 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::CancelAllCommands(PVMFSessionId aSession, const OsclAny* aContext)
686 {
687     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::CancelAllCommands"));
688     PVMp4FFCNCmd cmd;
689     cmd.Construct(aSession, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
690     return QueueCommandL(cmd);
691 }
692 
693 ////////////////////////////////////////////////////////////////////////////
CancelCommand(PVMFSessionId aSession,PVMFCommandId aCmdId,const OsclAny * aContext)694 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::CancelCommand(PVMFSessionId aSession, PVMFCommandId aCmdId, const OsclAny* aContext)
695 {
696     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::CancelCommand"));
697     PVMp4FFCNCmd cmd;
698     cmd.Construct(aSession, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
699     return QueueCommandL(cmd);
700 }
701 
702 ////////////////////////////////////////////////////////////////////////////
addRef()703 OSCL_EXPORT_REF void PVMp4FFComposerNode::addRef()
704 {
705     ++iExtensionRefCount;
706 }
707 
708 ////////////////////////////////////////////////////////////////////////////
removeRef()709 OSCL_EXPORT_REF void PVMp4FFComposerNode::removeRef()
710 {
711     if (iExtensionRefCount > 0)
712         --iExtensionRefCount;
713 }
714 
715 ////////////////////////////////////////////////////////////////////////////
queryInterface(const PVUuid & uuid,PVInterface * & iface)716 OSCL_EXPORT_REF bool PVMp4FFComposerNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
717 {
718     if (uuid == KPVMp4FFCNClipConfigUuid)
719     {
720         PVMp4FFCNClipConfigInterface* myInterface = OSCL_STATIC_CAST(PVMp4FFCNClipConfigInterface*, this);
721         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
722         ++iExtensionRefCount;
723     }
724     else if (uuid == KPVMp4FFCNTrackConfigUuid)
725     {
726         PVMp4FFCNTrackConfigInterface* myInterface = OSCL_STATIC_CAST(PVMp4FFCNTrackConfigInterface*, this);
727         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
728         ++iExtensionRefCount;
729     }
730     else if (uuid == PvmfComposerSizeAndDurationUuid)
731     {
732         PvmfComposerSizeAndDurationInterface* myInterface = OSCL_STATIC_CAST(PvmfComposerSizeAndDurationInterface*, this);
733         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
734         ++iExtensionRefCount;
735     }
736     else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
737     {
738         PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
739         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
740         ++iExtensionRefCount;
741     }
742     else
743     {
744         iface = NULL;
745         return false;
746     }
747 
748     return true;
749 }
750 
751 ////////////////////////////////////////////////////////////////////////////
752 //            PVMp4FFCNClipConfigInterface routines
753 ////////////////////////////////////////////////////////////////////////////
ConvertLangCode(const OSCL_String & aLang)754 OSCL_EXPORT_REF uint16 PVMp4FFComposerNode::ConvertLangCode(const OSCL_String & aLang)
755 {
756     int i = 0;
757     char lang[LANG_CODE_SIZE] = {0};
758     oscl_strncpy(lang, aLang.get_cstr(), LANG_CODE_SIZE);
759 
760     uint16 lang_code = ((((uint16)lang[i] - 0x60) << 10) | (((uint16)lang[i+1] - 0x60) << 5) | ((uint16)lang[i+2] - 0x60));
761 
762     return lang_code;
763 }
764 /////////////////////////////////////////////////////////////////////////////
SetOutputFileName(const OSCL_wString & aFileName)765 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileName(const OSCL_wString& aFileName)
766 {
767     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
768         return false;
769 
770     iFileName = aFileName;
771     return PVMFSuccess;
772 }
773 //////////////////////////////////////////////////////////////////////////////
SetOutputFileDescriptor(const OsclFileHandle * aFileHandle)774 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileDescriptor(const OsclFileHandle* aFileHandle)
775 {
776     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
777         return false;
778 
779     iFileObject = OSCL_NEW(Oscl_File, (0, (OsclFileHandle *)aFileHandle));
780     iFileObject->SetPVCacheSize(0);
781     iFileObject->SetAsyncReadBufferSize(0);
782     iFileObject->SetNativeBufferSize(0);
783     iFileObject->SetLoggingEnable(false);
784     iFileObject->SetSummaryStatsLoggingEnable(false);
785     iFileObject->SetFileHandle((OsclFileHandle*)aFileHandle);
786 
787     //call open
788     int32 retval = iFileObject->Open(_STRLIT_CHAR("dummy"),
789                                      Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY,
790                                      iFs);
791 
792     if (retval == 0)
793     {
794         return PVMFSuccess;
795     }
796     return PVMFFailure;
797 }
798 ////////////////////////////////////////////////////////////////////////////
SetAuthoringMode(PVMp4FFCN_AuthoringMode aAuthoringMode)799 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAuthoringMode(PVMp4FFCN_AuthoringMode aAuthoringMode)
800 {
801     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
802         return PVMFErrInvalidState;
803 
804     iAuthoringMode = aAuthoringMode;
805     return PVMFSuccess;
806 }
807 
808 ////////////////////////////////////////////////////////////////////////////
SetPresentationTimescale(uint32 aTimescale)809 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetPresentationTimescale(uint32 aTimescale)
810 {
811     if (iInterfaceState != EPVMFNodeIdle &&
812             iInterfaceState != EPVMFNodeInitialized &&
813             iInterfaceState != EPVMFNodePrepared)
814         return PVMFErrInvalidState;
815 
816     iPresentationTimescale = aTimescale;
817     return PVMFSuccess;
818 }
819 
820 ////////////////////////////////////////////////////////////////////////////
SetVersion(const OSCL_wString & aVersion,const OSCL_String & aLangCode)821 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetVersion(const OSCL_wString& aVersion, const OSCL_String& aLangCode)
822 {
823     if (iInterfaceState != EPVMFNodeIdle &&
824             iInterfaceState != EPVMFNodeInitialized &&
825             iInterfaceState != EPVMFNodePrepared)
826         return PVMFErrInvalidState;
827 
828     iVersion.iDataString = aVersion;
829     iVersion.iLangCode = ConvertLangCode(aLangCode);
830     return PVMFSuccess;
831 }
832 
833 ////////////////////////////////////////////////////////////////////////////
SetTitle(const OSCL_wString & aTitle,const OSCL_String & aLangCode)834 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetTitle(const OSCL_wString& aTitle, const OSCL_String& aLangCode)
835 {
836     if (iInterfaceState != EPVMFNodeIdle &&
837             iInterfaceState != EPVMFNodeInitialized &&
838             iInterfaceState != EPVMFNodePrepared)
839         return PVMFErrInvalidState;
840 
841     iTitle.iDataString = aTitle;
842     iTitle.iLangCode = ConvertLangCode(aLangCode);
843     return PVMFSuccess;
844 }
845 
846 ////////////////////////////////////////////////////////////////////////////
SetAuthor(const OSCL_wString & aAuthor,const OSCL_String & aLangCode)847 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAuthor(const OSCL_wString& aAuthor, const OSCL_String& aLangCode)
848 {
849     if (iInterfaceState != EPVMFNodeIdle &&
850             iInterfaceState != EPVMFNodeInitialized &&
851             iInterfaceState != EPVMFNodePrepared)
852         return PVMFErrInvalidState;
853 
854     iAuthor.iDataString = aAuthor;
855     iAuthor.iLangCode = ConvertLangCode(aLangCode);
856     return PVMFSuccess;
857 }
858 
859 ////////////////////////////////////////////////////////////////////////////
SetCopyright(const OSCL_wString & aCopyright,const OSCL_String & aLangCode)860 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCopyright(const OSCL_wString& aCopyright, const OSCL_String& aLangCode)
861 {
862     if (iInterfaceState != EPVMFNodeIdle &&
863             iInterfaceState != EPVMFNodeInitialized &&
864             iInterfaceState != EPVMFNodePrepared)
865         return PVMFErrInvalidState;
866 
867     iCopyright.iDataString = aCopyright;
868     iCopyright.iLangCode = ConvertLangCode(aLangCode);
869     return PVMFSuccess;
870 }
871 
872 ////////////////////////////////////////////////////////////////////////////
SetDescription(const OSCL_wString & aDescription,const OSCL_String & aLangCode)873 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetDescription(const OSCL_wString& aDescription, const OSCL_String& aLangCode)
874 {
875     if (iInterfaceState != EPVMFNodeIdle &&
876             iInterfaceState != EPVMFNodeInitialized &&
877             iInterfaceState != EPVMFNodePrepared)
878         return PVMFErrInvalidState;
879 
880     iDescription.iDataString = aDescription;
881     iDescription.iLangCode = ConvertLangCode(aLangCode);
882     return PVMFSuccess;
883 }
884 
885 ////////////////////////////////////////////////////////////////////////////
SetRating(const OSCL_wString & aRating,const OSCL_String & aLangCode)886 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetRating(const OSCL_wString& aRating, const OSCL_String& aLangCode)
887 {
888     if (iInterfaceState != EPVMFNodeIdle &&
889             iInterfaceState != EPVMFNodeInitialized &&
890             iInterfaceState != EPVMFNodePrepared)
891         return PVMFErrInvalidState;
892 
893     iRating.iDataString = aRating;
894     iRating.iLangCode = ConvertLangCode(aLangCode);
895     return PVMFSuccess;
896 }
897 
898 ////////////////////////////////////////////////////////////////////////////
SetCreationDate(const OSCL_wString & aCreationDate)899 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCreationDate(const OSCL_wString& aCreationDate)
900 {
901     if (iInterfaceState != EPVMFNodeIdle &&
902             iInterfaceState != EPVMFNodeInitialized &&
903             iInterfaceState != EPVMFNodePrepared)
904         return PVMFErrInvalidState;
905 
906     iCreationDate = aCreationDate;
907     return PVMFSuccess;
908 }
909 
910 ////////////////////////////////////////////////////////////////////////////
SetRealTimeAuthoring(const bool aRealTime)911 PVMFStatus PVMp4FFComposerNode::SetRealTimeAuthoring(const bool aRealTime)
912 {
913     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
914         return PVMFErrInvalidState;
915 
916     iRealTimeTS = aRealTime;
917     return PVMFSuccess;
918 }
919 
920 ////////////////////////////////////////////////////////////////////////////
SetAlbumInfo(const OSCL_wString & aAlbumTitle,const OSCL_String & aLangCode)921 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAlbumInfo(const OSCL_wString& aAlbumTitle, const OSCL_String& aLangCode)
922 {
923     if (iInterfaceState != EPVMFNodeIdle &&
924             iInterfaceState != EPVMFNodeInitialized &&
925             iInterfaceState != EPVMFNodePrepared)
926         return PVMFErrInvalidState;
927 
928     iAlbumTitle.iDataString = aAlbumTitle;
929     iAlbumTitle.iLangCode = ConvertLangCode(aLangCode);
930     return PVMFSuccess;
931 }
932 
933 
934 ////////////////////////////////////////////////////////////////////////////
SetRecordingYear(uint16 aRecordingYear)935 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetRecordingYear(uint16 aRecordingYear)
936 {
937     if (iInterfaceState != EPVMFNodeIdle &&
938             iInterfaceState != EPVMFNodeInitialized &&
939             iInterfaceState != EPVMFNodePrepared)
940         return PVMFErrInvalidState;
941 
942     iRecordingYear = aRecordingYear;
943     return PVMFSuccess;
944 }
945 
946 ////////////////////////////////////////////////////////////////////////////
SetPerformer(const OSCL_wString & aPerformer,const OSCL_String & aLangCode)947 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetPerformer(const OSCL_wString& aPerformer, const OSCL_String& aLangCode)
948 {
949     if (iInterfaceState != EPVMFNodeIdle &&
950             iInterfaceState != EPVMFNodeInitialized &&
951             iInterfaceState != EPVMFNodePrepared)
952         return PVMFErrInvalidState;
953 
954     iPerformer.iDataString = aPerformer;
955     iPerformer.iLangCode = ConvertLangCode(aLangCode);
956     return PVMFSuccess;
957 }
958 
959 ////////////////////////////////////////////////////////////////////////////
SetGenre(const OSCL_wString & aGenre,const OSCL_String & aLangCode)960 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetGenre(const OSCL_wString& aGenre, const OSCL_String& aLangCode)
961 {
962     if (iInterfaceState != EPVMFNodeIdle &&
963             iInterfaceState != EPVMFNodeInitialized &&
964             iInterfaceState != EPVMFNodePrepared)
965         return PVMFErrInvalidState;
966 
967     iGenre.iDataString = aGenre;
968     iGenre.iLangCode = ConvertLangCode(aLangCode);
969     return PVMFSuccess;
970 }
971 ////////////////////////////////////////////////////////////////////////////
SetClassification(const OSCL_wString & aClassificationInfo,uint32 aClassificationEntity,uint16 aClassificationTable,const OSCL_String & aLangCode)972 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetClassification(const OSCL_wString& aClassificationInfo, uint32 aClassificationEntity, uint16 aClassificationTable, const OSCL_String& aLangCode)
973 {
974     if (iInterfaceState != EPVMFNodeIdle &&
975             iInterfaceState != EPVMFNodeInitialized &&
976             iInterfaceState != EPVMFNodePrepared)
977         return PVMFErrInvalidState;
978 
979     iClassification.iDataString = aClassificationInfo;
980     iClassification.iClassificationEntity = aClassificationEntity;
981     iClassification.iClassificationTable = aClassificationTable;
982     iClassification.iLangCode = ConvertLangCode(aLangCode);
983     return PVMFSuccess;
984 }
985 ////////////////////////////////////////////////////////////////////////////
SetKeyWord(const OSCL_wString & aKeyWordInfo,const OSCL_String & aLangCode)986 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetKeyWord(const OSCL_wString& aKeyWordInfo, const OSCL_String& aLangCode)
987 {
988     if (iInterfaceState != EPVMFNodeIdle &&
989             iInterfaceState != EPVMFNodeInitialized &&
990             iInterfaceState != EPVMFNodePrepared)
991         return PVMFErrInvalidState;
992 
993     PVMP4FFCN_KeyWord *KeyWord = NULL;
994 
995     uint16 langCode = ConvertLangCode(aLangCode);
996     KeyWord = OSCL_NEW(PVMP4FFCN_KeyWord, (aKeyWordInfo, aKeyWordInfo.get_size(), langCode));
997 
998     iKeyWordVector.push_back(KeyWord);
999 
1000 
1001     return PVMFSuccess;
1002 }
1003 
1004 ////////////////////////////////////////////////////////////////////////////
SetLocationInfo(PvmfAssetInfo3GPPLocationStruct & aLocation_info)1005 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetLocationInfo(PvmfAssetInfo3GPPLocationStruct& aLocation_info)
1006 {
1007     if (iInterfaceState != EPVMFNodeIdle &&
1008             iInterfaceState != EPVMFNodeInitialized &&
1009             iInterfaceState != EPVMFNodePrepared)
1010         return PVMFErrInvalidState;
1011 
1012     iLocationInfo._location_name = NULL;
1013     uint32 size = oscl_strlen(aLocation_info._location_name);
1014     iLocationInfo._location_name = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10);
1015     oscl_strncpy(iLocationInfo._location_name, aLocation_info._location_name, size);
1016     iLocationInfo._location_name[size+1] = 0;
1017 
1018     iLocationInfo._astronomical_body = NULL;
1019     size = oscl_strlen(aLocation_info._astronomical_body);
1020     iLocationInfo._astronomical_body = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10);
1021     oscl_strncpy(iLocationInfo._astronomical_body, aLocation_info._astronomical_body, size);
1022     iLocationInfo._astronomical_body[size+1] = 0;
1023 
1024     iLocationInfo._additional_notes = NULL;
1025     size = oscl_strlen(aLocation_info._additional_notes);
1026     iLocationInfo._additional_notes = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10);
1027     oscl_strncpy(iLocationInfo._additional_notes, aLocation_info._additional_notes, size);
1028     iLocationInfo._additional_notes[size+1] = 0;
1029 
1030     iLocationInfo._role = aLocation_info._role;
1031     iLocationInfo._longitude = aLocation_info._longitude;
1032     iLocationInfo._latitude = aLocation_info._latitude;
1033     iLocationInfo._altitude = aLocation_info._altitude;
1034     iLocationInfo._langCode = ConvertLangCode(aLocation_info.Lang_code);
1035 
1036     return PVMFSuccess;
1037 }
1038 
1039 
1040 ////////////////////////////////////////////////////////////////////////////
1041 //                PVMp4FFCNTrackConfigInterface routines
1042 ////////////////////////////////////////////////////////////////////////////
SetTrackReference(const PVMFPortInterface & aPort,const PVMFPortInterface & aReferencePort)1043 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetTrackReference(const PVMFPortInterface& aPort,
1044         const PVMFPortInterface& aReferencePort)
1045 {
1046     if (iInterfaceState != EPVMFNodeInitialized)
1047         return PVMFErrInvalidState;
1048 
1049     int32 portIndex = -1;
1050     int32 refPortIndex = -1;
1051     PVMp4FFComposerPort* port = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, &aPort);
1052     PVMp4FFComposerPort* refPort = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, &aReferencePort);
1053 
1054     for (uint32 i = 0; i < iInPorts.size(); i++)
1055     {
1056         if (iInPorts[i] == port)
1057             portIndex = i;
1058         if (iInPorts[i] == refPort)
1059             refPortIndex = i;
1060     }
1061 
1062     if (portIndex > 0 && refPortIndex > 0)
1063     {
1064         iInPorts[portIndex]->SetReferencePort(iInPorts[refPortIndex]);
1065         return PVMFSuccess;
1066     }
1067     else
1068         return PVMFFailure;
1069 }
1070 
1071 ////////////////////////////////////////////////////////////////////////////
SetCodecSpecificInfo(const PVMFPortInterface & aPort,uint8 * aInfo,int32 aSize)1072 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCodecSpecificInfo(const PVMFPortInterface& aPort,
1073         uint8* aInfo, int32 aSize)
1074 {
1075     PVMFStatus status = PVMFFailure;
1076 
1077     if ((status == PVMFSuccess) &&
1078             (iInterfaceState == EPVMFNodeStarted))
1079     {
1080         PVMp4FFComposerPort* port = OSCL_STATIC_CAST(PVMp4FFComposerPort*, &aPort);
1081         iMpeg4File->setDecoderSpecificInfo(aInfo, aSize, port->GetTrackId());
1082     }
1083 
1084     return status;
1085 }
1086 
1087 ////////////////////////////////////////////////////////////////////////////
1088 //          PvmfComposerSizeAndDurationInterface routines
1089 ////////////////////////////////////////////////////////////////////////////
SetMaxFileSize(bool aEnable,uint32 aMaxFileSizeBytes)1090 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetMaxFileSize(bool aEnable, uint32 aMaxFileSizeBytes)
1091 {
1092     iMaxFileSizeEnabled = aEnable;
1093     if (iMaxFileSizeEnabled)
1094     {
1095         iMaxFileSize = aMaxFileSizeBytes;
1096     }
1097     else
1098     {
1099         iMaxFileSize = 0;
1100     }
1101 
1102     return PVMFSuccess;
1103 }
1104 
1105 ////////////////////////////////////////////////////////////////////////////
GetMaxFileSizeConfig(bool & aEnable,uint32 & aMaxFileSizeBytes)1106 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetMaxFileSizeConfig(bool& aEnable, uint32& aMaxFileSizeBytes)
1107 {
1108     aEnable = iMaxFileSizeEnabled;
1109     aMaxFileSizeBytes = iMaxFileSize;
1110 }
1111 
1112 ////////////////////////////////////////////////////////////////////////////
SetMaxDuration(bool aEnable,uint32 aMaxDurationMilliseconds)1113 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetMaxDuration(bool aEnable, uint32 aMaxDurationMilliseconds)
1114 {
1115     iMaxDurationEnabled = aEnable;
1116     if (iMaxDurationEnabled)
1117     {
1118         iMaxTimeDuration = aMaxDurationMilliseconds;
1119     }
1120     else
1121     {
1122         iMaxTimeDuration = 0;
1123     }
1124 
1125     return PVMFSuccess;
1126 }
1127 
1128 ////////////////////////////////////////////////////////////////////////////
GetMaxDurationConfig(bool & aEnable,uint32 & aMaxDurationMilliseconds)1129 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetMaxDurationConfig(bool& aEnable, uint32& aMaxDurationMilliseconds)
1130 {
1131     aEnable = iMaxDurationEnabled;
1132     aMaxDurationMilliseconds = iMaxTimeDuration;
1133 }
1134 
1135 ////////////////////////////////////////////////////////////////////////////
SetFileSizeProgressReport(bool aEnable,uint32 aReportFrequency)1136 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetFileSizeProgressReport(bool aEnable, uint32 aReportFrequency)
1137 {
1138     iFileSizeReportEnabled = aEnable;
1139     if (iFileSizeReportEnabled)
1140     {
1141         iFileSizeReportFreq = aReportFrequency;
1142     }
1143 
1144     return PVMFSuccess;
1145 }
1146 
1147 ////////////////////////////////////////////////////////////////////////////
GetFileSizeProgressReportConfig(bool & aEnable,uint32 & aReportFrequency)1148 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetFileSizeProgressReportConfig(bool& aEnable, uint32& aReportFrequency)
1149 {
1150     aEnable = iFileSizeReportEnabled;
1151     aReportFrequency = iFileSizeReportFreq;
1152 }
1153 
1154 ////////////////////////////////////////////////////////////////////////////
SetDurationProgressReport(bool aEnable,uint32 aReportFrequency)1155 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetDurationProgressReport(bool aEnable, uint32 aReportFrequency)
1156 {
1157     iDurationReportEnabled = aEnable;
1158     if (iDurationReportEnabled)
1159     {
1160         iDurationReportFreq = aReportFrequency;
1161     }
1162 
1163     return PVMFSuccess;
1164 }
1165 
1166 ////////////////////////////////////////////////////////////////////////////
GetDurationProgressReportConfig(bool & aEnable,uint32 & aReportFrequency)1167 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetDurationProgressReportConfig(bool& aEnable, uint32& aReportFrequency)
1168 {
1169     aEnable = iDurationReportEnabled;
1170     aReportFrequency = iDurationReportFreq;
1171 }
1172 
1173 ////////////////////////////////////////////////////////////////////////////
1174 //            PVMFPortActivityHandler routines
1175 ////////////////////////////////////////////////////////////////////////////
HandlePortActivity(const PVMFPortActivity & aActivity)1176 void PVMp4FFComposerNode::HandlePortActivity(const PVMFPortActivity& aActivity)
1177 {
1178     OSCL_UNUSED_ARG(aActivity);
1179     // Scheduling to process port activities are handled in the port itself
1180 }
1181 
1182 ////////////////////////////////////////////////////////////////////////////
1183 //                    OsclActiveObject routines
1184 ////////////////////////////////////////////////////////////////////////////
Run()1185 void PVMp4FFComposerNode::Run()
1186 {
1187     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::Run: iInterfaceState=%d", iInterfaceState));
1188 
1189     if (!iCmdQueue.empty())
1190     {
1191         if (ProcessCommand(iCmdQueue.front()))
1192         {
1193             //note: need to check the state before re-scheduling
1194             //since the node could have been reset in the ProcessCommand
1195             //call.
1196             if (iInterfaceState != EPVMFNodeCreated)
1197                 RunIfNotReady();
1198             return;
1199         }
1200     }
1201 
1202     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::Run: Out. iInterfaceState=%d", iInterfaceState));
1203 }
1204 
1205 
1206 ////////////////////////////////////////////////////////////////////////////
1207 //                   Command Processing routines
1208 ////////////////////////////////////////////////////////////////////////////
QueueCommandL(PVMp4FFCNCmd & aCmd)1209 PVMFCommandId PVMp4FFComposerNode::QueueCommandL(PVMp4FFCNCmd& aCmd)
1210 {
1211     int32 err = 0;
1212     PVMFCommandId id = 0;
1213 
1214     OSCL_TRY(err, id = iCmdQueue.AddL(aCmd););
1215     OSCL_FIRST_CATCH_ANY(err,
1216                          OSCL_LEAVE(err);
1217                          return 0;
1218                         );
1219 
1220     // Wakeup the AO
1221     RunIfNotReady();
1222     return id;
1223 }
1224 
1225 ////////////////////////////////////////////////////////////////////////////
ProcessCommand(PVMp4FFCNCmd & aCmd)1226 bool PVMp4FFComposerNode::ProcessCommand(PVMp4FFCNCmd& aCmd)
1227 {
1228     //normally this node will not start processing one command
1229     //until the prior one is finished.  However, a hi priority
1230     //command such as Cancel must be able to interrupt a command
1231     //in progress.
1232     if (!iCurrentCmd.empty() && !aCmd.hipri())
1233         return false;
1234 
1235     switch (aCmd.iCmd)
1236     {
1237         case PVMF_GENERIC_NODE_QUERYUUID:
1238             DoQueryUuid(aCmd);
1239             break;
1240 
1241         case PVMF_GENERIC_NODE_QUERYINTERFACE:
1242             DoQueryInterface(aCmd);
1243             break;
1244 
1245         case PVMF_GENERIC_NODE_REQUESTPORT:
1246             DoRequestPort(aCmd);
1247             break;
1248 
1249         case PVMF_GENERIC_NODE_RELEASEPORT:
1250             DoReleasePort(aCmd);
1251             break;
1252 
1253         case PVMF_GENERIC_NODE_INIT:
1254             DoInit(aCmd);
1255             break;
1256 
1257         case PVMF_GENERIC_NODE_PREPARE:
1258             DoPrepare(aCmd);
1259             break;
1260 
1261         case PVMF_GENERIC_NODE_START:
1262             DoStart(aCmd);
1263             break;
1264 
1265         case PVMF_GENERIC_NODE_STOP:
1266             DoStop(aCmd);
1267             break;
1268 
1269         case PVMF_GENERIC_NODE_FLUSH:
1270             DoFlush(aCmd);
1271             break;
1272 
1273         case PVMF_GENERIC_NODE_PAUSE:
1274             DoPause(aCmd);
1275             break;
1276 
1277         case PVMF_GENERIC_NODE_RESET:
1278             DoReset(aCmd);
1279             break;
1280 
1281         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
1282             DoCancelAllCommands(aCmd);
1283             break;
1284 
1285         case PVMF_GENERIC_NODE_CANCELCOMMAND:
1286             DoCancelCommand(aCmd);
1287             break;
1288 
1289         default://unknown command type
1290             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1291             break;
1292     }
1293 
1294     return true;
1295 }
1296 
1297 ////////////////////////////////////////////////////////////////////////////
CommandComplete(PVMp4FFCNCmdQueue & aCmdQueue,PVMp4FFCNCmd & aCmd,PVMFStatus aStatus,OsclAny * aEventData)1298 void PVMp4FFComposerNode::CommandComplete(PVMp4FFCNCmdQueue& aCmdQueue, PVMp4FFCNCmd& aCmd,
1299         PVMFStatus aStatus, OsclAny* aEventData)
1300 {
1301     LOG_STACK_TRACE((0, "PVMp4FFComposerNode:CommandComplete: Id %d Cmd %d Status %d Context %d Data %d"
1302                      , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
1303 
1304     //create response
1305     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData);
1306     PVMFSessionId session = aCmd.iSession;
1307 
1308     //Erase the command from the queue.
1309     aCmdQueue.Erase(&aCmd);
1310 
1311     //Report completion to the session observer.
1312     ReportCmdCompleteEvent(session, resp);
1313 }
1314 
1315 //////////////////////////////////////////////////////////////////////////////////
DoQueryUuid(PVMp4FFCNCmd & aCmd)1316 void PVMp4FFComposerNode::DoQueryUuid(PVMp4FFCNCmd& aCmd)
1317 {
1318     OSCL_String* mimetype;
1319     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
1320     bool exactmatch;
1321     aCmd.Parse(mimetype, uuidvec, exactmatch);
1322 
1323     uuidvec->push_back(KPVMp4FFCNClipConfigUuid);
1324     uuidvec->push_back(KPVMp4FFCNTrackConfigUuid);
1325     uuidvec->push_back(PvmfComposerSizeAndDurationUuid);
1326 
1327     CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1328 }
1329 
1330 //////////////////////////////////////////////////////////////////////////////////
DoQueryInterface(PVMp4FFCNCmd & aCmd)1331 void PVMp4FFComposerNode::DoQueryInterface(PVMp4FFCNCmd& aCmd)
1332 {
1333     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1334                     (0, "PVMp4FFComposerNode::DoQueryInterface"));
1335 
1336     PVUuid* uuid;
1337     PVInterface** ptr;
1338     aCmd.Parse(uuid, ptr);
1339 
1340     if (queryInterface(*uuid, *ptr))
1341     {
1342         CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1343     }
1344     else
1345     {
1346         CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1347     }
1348 }
1349 
1350 
1351 //////////////////////////////////////////////////////////////////////////////////
DoRequestPort(PVMp4FFCNCmd & aCmd)1352 void PVMp4FFComposerNode::DoRequestPort(PVMp4FFCNCmd& aCmd)
1353 {
1354     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1355                     (0, "PVMp4FFComposerNode::DoRequestPort() In"));
1356 
1357     int32 tag;
1358     OSCL_String* portconfig;
1359     aCmd.Parse(tag, portconfig);
1360 
1361     //validate the tag...
1362     switch (tag)
1363     {
1364         case PVMF_MP4FFCN_PORT_TYPE_SINK:
1365             if (iInPorts.size() >= PVMF_MP4FFCN_MAX_INPUT_PORT)
1366             {
1367                 LOG_ERR((0, "PVMp4FFComposerNode::DoRequestPort: Error - Max number of input port already allocated"));
1368                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1369                 return;
1370             }
1371             break;
1372 
1373         default:
1374             //bad port tag
1375             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1376                             (0, "PVMp4FFComposerNode::DoRequestPort: Error - Invalid port tag"));
1377             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1378             return;
1379     }
1380 
1381     //Allocate a new port
1382     OsclAny *ptr = NULL;
1383     int32 err;
1384     OSCL_TRY(err,
1385              ptr = iInPorts.Allocate();
1386              if (!ptr)
1387              OSCL_LEAVE(OsclErrNoMemory);
1388             );
1389 
1390     OSCL_FIRST_CATCH_ANY(err,
1391                          PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1392                                          (0, "PVMp4FFComposerNode::DoRequestPort: Error - iInPorts Out of memory"));
1393                          CommandComplete(iCmdQueue, aCmd, PVMFErrNoMemory);
1394                          return;
1395                         );
1396 
1397     OSCL_StackString<20> portname;
1398     portname = "PVMP4ComposerIn";
1399 
1400     PVMp4FFComposerPort* port = OSCL_PLACEMENT_NEW(ptr, PVMp4FFComposerPort(tag, this, Priority(), portname.get_cstr()));
1401 
1402     // if format was provided in mimestring, set it now.
1403     if (portconfig)
1404     {
1405         PVMFFormatType format = portconfig->get_str();
1406         if (format == PVMF_MIME_3GPP_TIMEDTEXT ||
1407                 format == PVMF_MIME_H264_VIDEO_MP4 ||
1408                 format == PVMF_MIME_M4V ||
1409                 format == PVMF_MIME_H2631998 ||
1410                 format == PVMF_MIME_H2632000 ||
1411                 format == PVMF_MIME_AMR_IETF ||
1412                 format == PVMF_MIME_AMRWB_IETF ||
1413                 format == PVMF_MIME_ADIF ||
1414                 format == PVMF_MIME_ADTS ||
1415                 format == PVMF_MIME_MPEG4_AUDIO)
1416         {
1417             port->SetFormat(format);
1418         }
1419         else
1420         {
1421             CommandComplete(iCmdQueue, aCmd, PVMFErrNotSupported);
1422             return;
1423         }
1424     }
1425 
1426     //Add the port to the port vector.
1427     OSCL_TRY(err, iInPorts.AddL(port););
1428     OSCL_FIRST_CATCH_ANY(err,
1429                          iInPorts.DestructAndDealloc(port);
1430                          CommandComplete(iCmdQueue, aCmd, PVMFErrNoMemory);
1431                          return;
1432                         );
1433 
1434     // Return the port pointer to the caller.
1435     CommandComplete(iCmdQueue, aCmd, PVMFSuccess, (OsclAny*)port);
1436 }
1437 
1438 //////////////////////////////////////////////////////////////////////////////////
DoReleasePort(PVMp4FFCNCmd & aCmd)1439 void PVMp4FFComposerNode::DoReleasePort(PVMp4FFCNCmd& aCmd)
1440 {
1441     //Find the port in the port vector
1442     PVMFPortInterface* p = NULL;
1443 
1444     for (uint32 i = 0; i < iInPorts.size(); i++)
1445     {
1446         aCmd.Parse(p);
1447 
1448         PVMp4FFComposerPort* port = (PVMp4FFComposerPort*)p;
1449 
1450         PVMp4FFComposerPort** portPtr = iInPorts.FindByValue(port);
1451         if (portPtr)
1452         {
1453             //delete the port.
1454             iInPorts.Erase(portPtr);
1455 
1456 #ifdef _TEST_AE_ERROR_HANDLING
1457             if (FAIL_NODE_CMD_RELEASE_PORT == iErrorNodeCmd)
1458             {
1459                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1460 
1461             }
1462             else
1463             {
1464                 CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1465             }
1466 #else
1467             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1468 #endif
1469 
1470         }
1471         else
1472         {
1473             //port not found.
1474             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1475         }
1476 
1477     }
1478 }
1479 
1480 //////////////////////////////////////////////////////////////////////////////////
DoInit(PVMp4FFCNCmd & aCmd)1481 void PVMp4FFComposerNode::DoInit(PVMp4FFCNCmd& aCmd)
1482 {
1483     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::DoInitNode() In"));
1484 
1485     switch (iInterfaceState)
1486     {
1487         case EPVMFNodeIdle:
1488             // Creation of file format library is done in DoStart. Nothing to do here.
1489             SetState(EPVMFNodeInitialized);
1490             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1491             break;
1492         case EPVMFNodeInitialized:
1493             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1494             break;
1495 
1496         default:
1497             CommandComplete(iCmdQueue, aCmd, PVMFErrInvalidState);
1498             break;
1499     }
1500 }
1501 
1502 //////////////////////////////////////////////////////////////////////////////////
DoPrepare(PVMp4FFCNCmd & aCmd)1503 void PVMp4FFComposerNode::DoPrepare(PVMp4FFCNCmd& aCmd)
1504 {
1505     switch (iInterfaceState)
1506     {
1507         case EPVMFNodeInitialized:
1508             // Creation of file format library is done in DoStart. Nothing to do here.
1509             SetState(EPVMFNodePrepared);
1510             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1511             break;
1512         case EPVMFNodePrepared:
1513             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1514             break;
1515 
1516         default:
1517             CommandComplete(iCmdQueue, aCmd, PVMFErrInvalidState);
1518             break;
1519     }
1520 }
1521 
1522 //////////////////////////////////////////////////////////////////////////////////
DoStart(PVMp4FFCNCmd & aCmd)1523 void PVMp4FFComposerNode::DoStart(PVMp4FFCNCmd& aCmd)
1524 {
1525     PVMFStatus status = PVMFSuccess;
1526     uint32 i = 0;
1527 #ifdef _TEST_AE_ERROR_HANDLING
1528     if (FAIL_NODE_CMD_START == iErrorNodeCmd)
1529     {
1530         iInterfaceState = EPVMFNodeError;
1531     }
1532 #endif
1533     switch (iInterfaceState)
1534     {
1535         case EPVMFNodePrepared:
1536         {
1537             iPostfix = _STRLIT("00");
1538             iOutputPath = _STRLIT("");
1539             int32 pos = 0;
1540             for (pos = iFileName.get_size() - 1; pos >= 0; pos--)
1541             {
1542                 if (iFileName[pos] == SLASH)
1543                     break;
1544             }
1545 
1546             if (pos == -1)
1547             {
1548                 iOutputPath = _STRLIT(".");
1549             }
1550             else
1551             {
1552                 for (i = 0; i <= (uint32) pos; i++)
1553                     iOutputPath += iFileName[i];
1554             }
1555 
1556 
1557 
1558             iFileType = 0;
1559             for (i = 0; i < iInPorts.size(); i++)
1560             {
1561                 if (iInPorts[i]->GetFormat() == PVMF_MIME_H264_VIDEO_MP4 ||
1562                         iInPorts[i]->GetFormat() == PVMF_MIME_M4V ||
1563                         iInPorts[i]->GetFormat() == PVMF_MIME_H2631998 ||
1564                         iInPorts[i]->GetFormat() == PVMF_MIME_H2632000)
1565                 {
1566                     iFileType |= FILE_TYPE_VIDEO;
1567                 }
1568                 else if (iInPorts[i]->GetFormat() == PVMF_MIME_AMR_IETF ||
1569                          iInPorts[i]->GetFormat() == PVMF_MIME_AMRWB_IETF ||
1570                          iInPorts[i]->GetFormat() == PVMF_MIME_MPEG4_AUDIO)
1571                 {
1572                     iFileType |= FILE_TYPE_AUDIO;
1573                 }
1574                 else if (iInPorts[i]->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT)
1575                 {
1576                     iFileType |= FILE_TYPE_TIMED_TEXT;
1577                 }
1578                 else
1579                 {
1580                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1581                                     (0, "PVMp4FFComposerNode::DoStart: Error - Unsupported format"));
1582                     return;
1583                 }
1584             }
1585 
1586             if (iMpeg4File)
1587             {
1588                 LOG_ERR((0, "PVMp4FFComposerNode::DoStart: Error - File format library already exists"));
1589                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1590                 return;
1591             }
1592 
1593             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1594                             (0, "PVMp4FFComposerNode::DoStart: Calling PVA_FF_IMpeg4File::createMP4File(%d,0x%x,%d)",
1595                              iFileType, &iFs, iAuthoringMode));
1596 #ifdef _TEST_AE_ERROR_HANDLING //test case to fail mp4 file parser
1597             if (iErrorCreateComposer)
1598             {
1599                 //to fail createMP4File()
1600                 OSCL_wHeapString<OsclMemAllocator> ErrFileName;
1601 
1602                 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
1603                              (void*) & iFs, iAuthoringMode, ErrFileName, iCacheSize);
1604 
1605             }
1606             else
1607             {
1608                 if (iFileObject != NULL)
1609                 {
1610                     iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iFileObject, iCacheSize);
1611 
1612                 }
1613                 else
1614                 {
1615 
1616                     iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
1617                                  (void*) & iFs, iAuthoringMode, iFileName, iCacheSize);
1618 
1619                 }
1620             }
1621 #else
1622             if (iFileObject != NULL)
1623             {
1624                 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iFileObject, iCacheSize);
1625 
1626             }
1627             else
1628             {
1629                 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
1630                              (void*) & iFs, iAuthoringMode, iFileName, iCacheSize);
1631             }
1632 #endif
1633             if (!iMpeg4File)
1634             {
1635                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1636                                 (0, "PVMp4FFComposerNode::DoStart: Error - PVA_FF_IMpeg4File::createMP4File failed"));
1637                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1638                 return;
1639             }
1640 
1641             iMpeg4File->setPresentationTimescale(iPresentationTimescale);
1642             iMpeg4File->setVersion(iVersion.iDataString, iVersion.iLangCode);
1643             iMpeg4File->setTitle(iTitle.iDataString, iTitle.iLangCode);
1644             iMpeg4File->setAuthor(iAuthor.iDataString, iAuthor.iLangCode);
1645             iMpeg4File->setCopyright(iCopyright.iDataString, iCopyright.iLangCode);
1646             iMpeg4File->setDescription(iDescription.iDataString, iDescription.iLangCode);
1647             iMpeg4File->setRating(iRating.iDataString, iRating.iLangCode);
1648             iMpeg4File->setCreationDate(iCreationDate);
1649             iMpeg4File->setMovieFragmentDuration(iMovieFragmentDuration);
1650             iMpeg4File->setAlbumInfo(iAlbumTitle.iDataString, iAlbumTitle.iLangCode);
1651             iMpeg4File->setRecordingYear(iRecordingYear);
1652 
1653             iMpeg4File->setPerformer(iPerformer.iDataString, iPerformer.iLangCode);
1654             iMpeg4File->setGenre(iGenre.iDataString, iGenre.iLangCode);
1655             iMpeg4File->setClassification(iClassification.iDataString, iClassification.iClassificationEntity, iClassification.iClassificationTable, iClassification.iLangCode);
1656 
1657             for (i = 0; i < iKeyWordVector.size() ; i++)
1658             {
1659                 iMpeg4File->setKeyWord(iKeyWordVector[i]->iKeyWordSize, iKeyWordVector[i]->iData_String, iKeyWordVector[i]->iLang_Code);
1660             }
1661 
1662             iMpeg4File->setLocationInfo(&iLocationInfo);
1663             for (i = 0; i < iInPorts.size(); i++)
1664             {
1665                 status = AddTrack(iInPorts[i]);
1666                 if (status != PVMFSuccess)
1667                 {
1668                     CommandComplete(iCmdQueue, aCmd, status);
1669                     return;
1670                 }
1671             }
1672 
1673             // Check for and set reference tracks after track IDs are assigned
1674             PVMp4FFComposerPort* refPort = NULL;
1675             for (i = 0; i < iInPorts.size(); i++)
1676             {
1677                 refPort = OSCL_STATIC_CAST(PVMp4FFComposerPort*, iInPorts[i]->GetReferencePort());
1678                 if (refPort)
1679                 {
1680                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1681                                     (0, "PVMp4FFComposerNode::DoStart: Calling addTrackReference(%d, %d)",
1682                                      iInPorts[i]->GetTrackId(), refPort->GetTrackId()));
1683                     iMpeg4File->addTrackReference(iInPorts[i]->GetTrackId(), refPort->GetTrackId());
1684                 }
1685             }
1686 
1687             iMpeg4File->prepareToEncode();
1688 
1689             iInitTSOffset = true;
1690             iTSOffset = 0;
1691             SetState(EPVMFNodeStarted);
1692             break;
1693         }
1694 
1695         case EPVMFNodePaused:
1696             SetState(EPVMFNodeStarted);
1697             for (i = 0; i < iInPorts.size(); i++)
1698                 ((PVMp4FFComposerPort*)iInPorts[i])->ProcessIncomingMsgReady();
1699             break;
1700         case EPVMFNodeStarted:
1701             status = PVMFSuccess;
1702             break;
1703         default:
1704             status = PVMFErrInvalidState;
1705             break;
1706     }
1707 
1708     CommandComplete(iCmdQueue, aCmd, status);
1709 }
1710 
1711 //////////////////////////////////////////////////////////////////////////////////
AddTrack(PVMp4FFComposerPort * aPort)1712 PVMFStatus PVMp4FFComposerNode::AddTrack(PVMp4FFComposerPort *aPort)
1713 {
1714     int32 codecType = 0;
1715     int32 mediaType = 0;
1716     int32 trackId = 0;
1717     PVMP4FFCNFormatSpecificConfig* config = aPort->GetFormatSpecificConfig();
1718     if (!config)
1719     {
1720         LOG_ERR((0, "PVMp4FFComposerNode::AddTrack: Error - GetFormatSpecificConfig failed"));
1721         return PVMFFailure;
1722     }
1723 
1724     if (aPort->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT)
1725     {
1726         codecType = CODEC_TYPE_TIMED_TEXT;
1727         mediaType = MEDIA_TYPE_TEXT;
1728     }
1729     else if (aPort->GetFormat() == PVMF_MIME_H264_VIDEO_MP4)
1730     {
1731         codecType = CODEC_TYPE_AVC_VIDEO;
1732         mediaType = MEDIA_TYPE_VISUAL;
1733     }
1734     else if (aPort->GetFormat() == PVMF_MIME_M4V)
1735     {
1736         codecType = CODEC_TYPE_MPEG4_VIDEO;
1737         mediaType = MEDIA_TYPE_VISUAL;
1738     }
1739     else if (aPort->GetFormat() == PVMF_MIME_H2631998 ||
1740              aPort->GetFormat() == PVMF_MIME_H2632000)
1741     {
1742         codecType = CODEC_TYPE_BASELINE_H263_VIDEO;
1743         mediaType = MEDIA_TYPE_VISUAL;
1744     }
1745     else if (aPort->GetFormat() == PVMF_MIME_AMR_IETF)
1746     {
1747         codecType = CODEC_TYPE_AMR_AUDIO;
1748         mediaType = MEDIA_TYPE_AUDIO;
1749     }
1750     else if (aPort->GetFormat() == PVMF_MIME_AMRWB_IETF)
1751     {
1752         codecType = CODEC_TYPE_AMR_WB_AUDIO;
1753         mediaType = MEDIA_TYPE_AUDIO;
1754     }
1755     else if (aPort->GetFormat() ==  PVMF_MIME_MPEG4_AUDIO)
1756     {
1757         codecType = CODEC_TYPE_AAC_AUDIO;
1758         mediaType = MEDIA_TYPE_AUDIO;
1759     }
1760     else
1761     {
1762         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1763                         (0, "PVMp4FFComposerNode::AddTrack: Error - Unsupported format"));
1764         return PVMFFailure;
1765     }
1766 
1767     aPort->SetCodecType(codecType);
1768 
1769     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1770                     (0, "PVMp4FFComposerNode::AddTrack: Calling PVA_FF_IMpeg4File::addTrack(0x%x,0x%x)",
1771                      mediaType, codecType));
1772 #ifdef _TEST_AE_ERROR_HANDLING
1773     if (aPort->GetFormat() == iErrorAddTrack)
1774     {
1775         return PVMFFailure;
1776     }
1777 #endif
1778     trackId = iMpeg4File->addTrack(mediaType, codecType);
1779 #ifdef _TEST_AE_ERROR_HANDLING
1780     if (iErrorHandlingAddTrack)
1781     {
1782         trackId = 0;
1783     }
1784 #endif
1785     if (trackId == 0)
1786     {
1787         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1788                         (0, "PVMp4FFComposerNode::AddTrack: Error - PVA_FF_IMpeg4File::addTrack failed"));
1789         return PVMFFailure;
1790     }
1791     aPort->SetTrackId(trackId);
1792     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1793                     (0, "PVMp4FFComposerNode::AddTrack: PVA_FF_IMpeg4File::addTrack success. trackID=%d", trackId));
1794 #if PROFILING_ON
1795 
1796     for (uint32 k = 0; k < 3; k++)
1797     {
1798         if (iStats[k].iTrackId == 0)
1799         {
1800             iStats[k].iTrackId = trackId;
1801             break;
1802         }
1803     }
1804 #endif
1805 
1806     switch (mediaType)
1807     {
1808         case MEDIA_TYPE_AUDIO:
1809             iMpeg4File->setTargetBitRate(trackId, config->iBitrate);
1810             iMpeg4File->setTimeScale(trackId, config->iTimescale);
1811             break;
1812 
1813         case MEDIA_TYPE_VISUAL:
1814             switch (codecType)
1815             {
1816                 case CODEC_TYPE_BASELINE_H263_VIDEO:
1817                     iMpeg4File->setH263ProfileLevel(trackId, config->iH263Profile, config->iH263Level);
1818                     // Don't break here. Continue to set other video properties
1819                 case CODEC_TYPE_AVC_VIDEO:
1820                 case CODEC_TYPE_MPEG4_VIDEO:
1821                     iMpeg4File->setTargetBitRate(trackId, config->iBitrate);
1822                     iMpeg4File->setTimeScale(trackId, config->iTimescale);
1823                     iMpeg4File->setVideoParams(trackId, (float)config->iFrameRate,
1824                                                (uint16)config->iIFrameInterval, config->iWidth, config->iHeight);
1825                     break;
1826             }
1827             break;
1828         case MEDIA_TYPE_TEXT:
1829             iMpeg4File->setTargetBitRate(trackId, config->iBitrate);
1830             iMpeg4File->setTimeScale(trackId, config->iTimescale);
1831             break;
1832 
1833     }
1834 
1835     return PVMFSuccess;
1836 }
1837 
1838 //////////////////////////////////////////////////////////////////////////////////
DoStop(PVMp4FFCNCmd & aCmd)1839 void PVMp4FFComposerNode::DoStop(PVMp4FFCNCmd& aCmd)
1840 {
1841     PVMFStatus status = PVMFSuccess;
1842 #if PROFILING_ON
1843     if (!oDiagnosticsLogged)
1844     {
1845         LogDiagnostics();
1846     }
1847 #endif
1848 #ifdef _TEST_AE_ERROR_HANDLING
1849     if (FAIL_NODE_CMD_STOP == iErrorNodeCmd)
1850     {
1851         iInterfaceState = EPVMFNodeError;
1852     }
1853 #endif
1854     switch (iInterfaceState)
1855     {
1856         case EPVMFNodeStarted:
1857         case EPVMFNodePaused:
1858         {
1859 #ifdef ANDROID
1860             iFragmentWriter->flush();
1861 #endif
1862             if (!iNodeEndOfDataReached)
1863             {
1864                 WriteDecoderSpecificInfo();
1865                 if (iSampleInTrack)
1866                 {
1867                     status = RenderToFile();
1868                 }
1869 
1870                 iSampleInTrack = false;
1871             }
1872 
1873             iNodeEndOfDataReached = false;
1874             for (uint32 ii = 0; ii < iInPorts.size(); ii++)
1875             {
1876                 iInPorts[ii]->iEndOfDataReached = false;
1877             }
1878         }
1879         SetState(EPVMFNodePrepared);
1880         break;
1881         case EPVMFNodePrepared:
1882             status = PVMFSuccess;
1883             break;
1884         default:
1885             status = PVMFErrInvalidState;
1886             break;
1887     }
1888 
1889     CommandComplete(iCmdQueue, aCmd, status);
1890 }
1891 
1892 //////////////////////////////////////////////////////////////////////////////////
WriteDecoderSpecificInfo()1893 void PVMp4FFComposerNode::WriteDecoderSpecificInfo()
1894 {
1895     uint32 i;
1896     uint32 offset = 0;
1897     iConfigSize = 0;
1898     int32 trackId;
1899 
1900     if (iformat_h264 == PVMF_MIME_H264_VIDEO_MP4)
1901     {
1902         trackId = iTrackId_H264;
1903 
1904         for (i = 0; i < memvector_sps.size(); i++)
1905         {
1906             iConfigSize += 2;//2 bytes for SPS_len
1907             iConfigSize += memvector_sps[i]->len;
1908         }
1909 
1910         for (i = 0; i < memvector_pps.size(); i++)
1911         {
1912             iConfigSize += 2;//2 bytes for PPS_len
1913             iConfigSize += memvector_pps[i]->len;
1914         }
1915         iConfigSize = iConfigSize + 2;//extra two bytes for nunSPS and NumPPS
1916         pConfig = (uint8*)(OSCL_MALLOC(sizeof(uint8) * iConfigSize));
1917 
1918 
1919         //currently we are ignoring NAL Length information
1920         oscl_memcpy((void*)(pConfig + offset), (const void*)&iNum_SPS_Set, 1);//Writing Number of SPS sets
1921         offset += 1;
1922 
1923         for (i = 0; i < memvector_sps.size(); i++)
1924         {
1925             oscl_memcpy((void*)(pConfig + offset), (const void*)&memvector_sps[i]->len, 2);//Writing length of SPS
1926             offset += 2;
1927             oscl_memcpy((void*)(pConfig + offset), memvector_sps[i]->ptr, memvector_sps[i]->len);
1928             offset = offset + memvector_sps[i]->len;
1929         }
1930 
1931         oscl_memcpy((void*)(pConfig + offset), (const void*)&iNum_PPS_Set, 1);//Writing Number of PPS sets
1932         offset += 1;
1933 
1934         for (i = 0; i < memvector_pps.size(); i++)
1935         {
1936             oscl_memcpy((void*)(pConfig + offset), (const void*)&memvector_pps[i]->len, 2);//Writing length of PPS
1937             offset += 2;//2 bytes for PPS Length
1938             oscl_memcpy((void*)(pConfig + offset), memvector_pps[i]->ptr, memvector_pps[i]->len);
1939             offset = offset + memvector_pps[i]->len;
1940         }
1941         iMpeg4File->setDecoderSpecificInfo(pConfig, iConfigSize, trackId);
1942     }
1943 
1944     if (iformat_text == PVMF_MIME_3GPP_TIMEDTEXT)
1945     {
1946         for (uint32 ii = 0; ii < textdecodervector.size(); ii++)
1947         {
1948             trackId = iTrackId_Text;
1949             iMpeg4File->setTextDecoderSpecificInfo(textdecodervector[ii], trackId);
1950         }
1951     }
1952 
1953 }
1954 //////////////////////////////////////////////////////////////////////////////////
RenderToFile()1955 PVMFStatus PVMp4FFComposerNode::RenderToFile()
1956 {
1957     PVMFStatus status = PVMFSuccess;
1958 
1959     // Clear queued messages in ports
1960     uint32 i;
1961     for (i = 0; i < iInPorts.size(); i++)
1962         iInPorts[i]->ClearMsgQueues();
1963 #ifdef _TEST_AE_ERROR_HANDLING //to fail renderToFile
1964     if (iErrorRenderToFile)
1965     {
1966         if (iMpeg4File)
1967         {
1968             PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
1969             iMpeg4File = NULL;
1970         }
1971     }
1972 #endif
1973 
1974 #ifdef ANDROID
1975     iFragmentWriter->flush();
1976 #endif
1977 
1978     if (!iMpeg4File || !iMpeg4File->renderToFile(iFileName))
1979     {
1980         LOG_ERR((0, "PVMp4FFComposerNode::RenderToFile: Error - renderToFile failed"));
1981         ReportErrorEvent(PVMF_MP4FFCN_ERROR_FINALIZE_OUTPUT_FILE_FAILED);
1982         status = PVMFFailure;
1983     }
1984     else
1985     {
1986 #if PROFILING_ON
1987         // Statistics
1988 
1989         for (i = 0; i < 3; i++)
1990         {
1991             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1992                             (0, "PVMp4FFComposerNode Stats: TrackId=%d, NumFrame=%d, Duration=%d",
1993                              iStats[i].iTrackId, iStats[i].iNumFrames, iStats[i].iDuration));
1994             oscl_memset(&(iStats[i]), 0, sizeof(PVMp4FFCNStats));
1995         }
1996 #endif
1997 
1998         LOGDATATRAFFIC((0, "PVMp4FFComposerNode::RenderToFile() Done"));
1999         // Delete file format library
2000         if (iMpeg4File)
2001         {
2002             PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
2003             iMpeg4File = NULL;
2004         }
2005 
2006         // Change state
2007         SetState(EPVMFNodePrepared);
2008         status = PVMFSuccess;
2009     }
2010 
2011     if (PVMFSuccess == status)
2012     {
2013         iFileRendered = true;
2014     }
2015     return status;
2016 }
2017 
2018 //////////////////////////////////////////////////////////////////////////////////
DoFlush(PVMp4FFCNCmd & aCmd)2019 void PVMp4FFComposerNode::DoFlush(PVMp4FFCNCmd& aCmd)
2020 {
2021     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::DoFlush() iInterfaceState:%d", iInterfaceState));
2022 #ifdef _TEST_AE_ERROR_HANDLING
2023     if (FAIL_NODE_CMD_FLUSH == iErrorNodeCmd)
2024     {
2025         iInterfaceState = EPVMFNodeError;
2026     }
2027 #endif
2028     switch (iInterfaceState)
2029     {
2030         case EPVMFNodeStarted:
2031         case EPVMFNodePaused:
2032             int32 err;
2033             uint32 i;
2034             bool msgPending;
2035             msgPending = false;
2036 
2037             for (i = 0; i < iInPorts.size(); i++)
2038             {
2039                 if (iInPorts[i]->IncomingMsgQueueSize() > 0)
2040                     msgPending = true;
2041                 iInPorts[i]->SuspendInput();
2042                 if (iInterfaceState != EPVMFNodeStarted)
2043                 {
2044                     // Port is in idle if node state is not started. Call ProcessIncomingMsgReady
2045                     // to wake up port AO
2046                     ((PVMp4FFComposerPort*)iInPorts[i])->ProcessIncomingMsgReady();
2047                 }
2048             }
2049 
2050             // Move the command from the input command queue to the current command, where
2051             // it will remain until the flush completes.
2052             err = StoreCurrentCommand(iCurrentCmd, aCmd, iCmdQueue);
2053             if (0 != err)
2054                 return;
2055 
2056             iCmdQueue.Erase(&aCmd);
2057 
2058             if (!msgPending)
2059             {
2060                 FlushComplete();
2061                 return;
2062             }
2063             break;
2064 
2065         default:
2066             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
2067             break;
2068     }
2069 }
2070 
2071 ////////////////////////////////////////////////////////////////////////////
IsFlushPending()2072 bool PVMp4FFComposerNode::IsFlushPending()
2073 {
2074     return (iCurrentCmd.size() > 0
2075             && iCurrentCmd.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
2076 }
2077 
2078 ////////////////////////////////////////////////////////////////////////////
FlushComplete()2079 void PVMp4FFComposerNode::FlushComplete()
2080 {
2081     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::FlushComplete"));
2082     uint32 i = 0;
2083     PVMFStatus status = PVMFSuccess;
2084     // Flush is complete only when all queues of all ports are clear.
2085     // Other wise, just return from this method and wait for FlushComplete
2086     // from the remaining ports.
2087     for (i = 0; i < iInPorts.size(); i++)
2088     {
2089         if (iInPorts[i]->IncomingMsgQueueSize() > 0 ||
2090                 iInPorts[i]->OutgoingMsgQueueSize() > 0)
2091         {
2092             return;
2093         }
2094     }
2095 #ifdef ANDROID
2096     iFragmentWriter->flush();
2097 #endif
2098     if (!iNodeEndOfDataReached)
2099     {
2100         WriteDecoderSpecificInfo();
2101         // Finalize output file
2102         if (iSampleInTrack)
2103         {
2104             status = RenderToFile();
2105         }
2106 
2107         iSampleInTrack = false;
2108 
2109         if (status != PVMFSuccess)
2110             LOG_ERR((0, "PVMp4FFComposerNode::FlushComplete: Error - RenderToFile failed"));
2111     }
2112 
2113     // Resume port input so the ports can be re-started.
2114     for (i = 0; i < iInPorts.size(); i++)
2115         iInPorts[i]->ResumeInput();
2116 
2117     SetState(EPVMFNodePrepared);
2118 
2119     if (!iCurrentCmd.empty())
2120     {
2121         CommandComplete(iCurrentCmd, iCurrentCmd[0], status);
2122     }
2123 
2124     if (!iCmdQueue.empty())
2125     {
2126         // If command queue is not empty, schedule to process the next command
2127         RunIfNotReady();
2128     }
2129 
2130 
2131 }
2132 
2133 //////////////////////////////////////////////////////////////////////////////////
DoPause(PVMp4FFCNCmd & aCmd)2134 void PVMp4FFComposerNode::DoPause(PVMp4FFCNCmd& aCmd)
2135 {
2136     PVMFStatus status = PVMFSuccess;
2137 
2138 #ifdef _TEST_AE_ERROR_HANDLING
2139     if (FAIL_NODE_CMD_PAUSE == iErrorNodeCmd)
2140     {
2141         iInterfaceState = EPVMFNodeError;
2142     }
2143 #endif
2144     switch (iInterfaceState)
2145     {
2146         case EPVMFNodeStarted:
2147             SetState(EPVMFNodePaused);
2148             break;
2149         case EPVMFNodePaused:
2150             break;
2151         default:
2152             status = PVMFErrInvalidState;
2153             break;
2154     }
2155 
2156     CommandComplete(iCmdQueue, aCmd, status);
2157 }
2158 
2159 //////////////////////////////////////////////////////////////////////////////////
DoReset(PVMp4FFCNCmd & aCmd)2160 void PVMp4FFComposerNode::DoReset(PVMp4FFCNCmd& aCmd)
2161 {
2162     PVMFStatus status = PVMFSuccess;
2163 #if PROFILING_ON
2164     if (!oDiagnosticsLogged)
2165     {
2166         LogDiagnostics();
2167     }
2168 #endif
2169 
2170     if (IsAdded())
2171     {
2172         if (iSampleInTrack)
2173         {
2174             status = RenderToFile();
2175             iSampleInTrack = false;
2176         }
2177 
2178         //delete all ports and notify observer.
2179         while (!iInPorts.empty())
2180             iInPorts.Erase(&iInPorts.front());
2181 
2182         //restore original port vector reserve.
2183         iInPorts.Reconstruct();
2184         iNodeEndOfDataReached = false;
2185 
2186         //logoff & go back to Created state.
2187         SetState(EPVMFNodeIdle);
2188         status = PVMFSuccess;
2189     }
2190     else
2191     {
2192         OSCL_LEAVE(OsclErrInvalidState);
2193     }
2194 
2195     CommandComplete(iCmdQueue, aCmd, status);
2196 }
2197 
2198 //////////////////////////////////////////////////////////////////////////////////
DoCancelAllCommands(PVMp4FFCNCmd & aCmd)2199 void PVMp4FFComposerNode::DoCancelAllCommands(PVMp4FFCNCmd& aCmd)
2200 {
2201     //first cancel the current command if any
2202     while (!iCurrentCmd.empty())
2203         CommandComplete(iCurrentCmd, iCurrentCmd[0], PVMFErrCancelled);
2204 
2205     //next cancel all queued commands
2206     //start at element 1 since this cancel command is element 0.
2207     while (iCmdQueue.size() > 1)
2208         CommandComplete(iCmdQueue, iCmdQueue[1], PVMFErrCancelled);
2209 
2210     //finally, report cancel complete.
2211     CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
2212 }
2213 
2214 //////////////////////////////////////////////////////////////////////////////////
DoCancelCommand(PVMp4FFCNCmd & aCmd)2215 void PVMp4FFComposerNode::DoCancelCommand(PVMp4FFCNCmd& aCmd)
2216 {
2217     //extract the command ID from the parameters.
2218     PVMFCommandId id;
2219     aCmd.Parse(id);
2220 
2221     //first check "current" command if any
2222     PVMp4FFCNCmd* cmd = iCurrentCmd.FindById(id);
2223     if (cmd)
2224     {
2225         //cancel the queued command
2226         CommandComplete(iCurrentCmd, *cmd, PVMFErrCancelled);
2227         //report cancel success
2228         CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
2229         return;
2230     }
2231 
2232     //next check input queue.
2233     //start at element 1 since this cancel command is element 0.
2234     cmd = iCmdQueue.FindById(id, 1);
2235     if (cmd)
2236     {
2237         //cancel the queued command
2238         CommandComplete(iCmdQueue, *cmd, PVMFErrCancelled);
2239         //report cancel success
2240         CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
2241         return;
2242     }
2243 
2244     //if we get here the command isn't queued so the cancel fails.
2245     CommandComplete(iCmdQueue, aCmd, PVMFFailure);
2246 }
2247 
2248 //////////////////////////////////////////////////////////////////////////////////
2249 //                  Port activity processing routines
2250 //////////////////////////////////////////////////////////////////////////////////
IsProcessIncomingMsgReady()2251 bool PVMp4FFComposerNode::IsProcessIncomingMsgReady()
2252 {
2253     if (iInterfaceState == EPVMFNodeStarted || IsFlushPending())
2254         return true;
2255     else
2256         return false;
2257 }
2258 
2259 ////////////////////////////////////////////////////////////////////////////
ProcessIncomingMsg(PVMFPortInterface * aPort)2260 PVMFStatus PVMp4FFComposerNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
2261 {
2262     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::ProcessIncomingMsg: aPort=0x%x", aPort));
2263     PVMFStatus status = PVMFSuccess;
2264 
2265     switch (aPort->GetPortTag())
2266     {
2267         case PVMF_MP4FFCN_PORT_TYPE_SINK:
2268         {
2269             PVMp4FFComposerPort* port = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, aPort);
2270             if (!IsProcessIncomingMsgReady())
2271             {
2272                 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Not ready."));
2273                 return PVMFErrBusy;
2274             }
2275 
2276             PVMFSharedMediaMsgPtr msg;
2277             status = port->DequeueIncomingMsg(msg);
2278             if (status != PVMFSuccess)
2279             {
2280                 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed"));
2281                 return status;
2282             }
2283             if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
2284             {
2285                 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::ProcessIncomingMsg: EOS Recvd - TrackID=%d, StreamID=%d, TS=%d, Mime=%s",
2286                                 port->GetTrackId(), msg->getStreamID(), msg->getTimestamp(), port->GetMimeType().get_cstr()));
2287 
2288                 port->iEndOfDataReached = true;
2289                 //check if EOS has been received on all connected ports.
2290                 uint32 ii = 0;
2291                 iNodeEndOfDataReached = true;
2292                 for (ii = 0; ii < iInPorts.size(); ii++)
2293                 {
2294                     if (!iInPorts[ii]->iEndOfDataReached)
2295                     {
2296                         iNodeEndOfDataReached = false;
2297                     }
2298                 }
2299 
2300                 if (iNodeEndOfDataReached)
2301                 {
2302                     //Close the file since EOS is received on every connected port
2303                     WriteDecoderSpecificInfo();
2304                     if (iSampleInTrack)
2305                     {
2306                         status = RenderToFile();
2307                         iSampleInTrack = false;
2308                     }
2309 
2310                     //report EOS info to engine
2311                     ReportInfoEvent(PVMF_COMPOSER_EOS_REACHED);
2312                 }
2313 
2314                 //since we do not have data to process, we can safely break here.
2315                 break;
2316             }
2317 
2318             PVMFSharedMediaDataPtr mediaDataPtr;
2319             convertToPVMFMediaData(mediaDataPtr, msg);
2320 
2321             int32 trackId = port->GetTrackId();
2322             if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_M4V))
2323             {
2324                 // Set VOL Header
2325                 OsclRefCounterMemFrag volHeader;
2326                 if (mediaDataPtr->getFormatSpecificInfo(volHeader) == false ||
2327                         volHeader.getMemFragSize() == 0)
2328                 {
2329                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2330                                     (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - VOL Header not available"));
2331                     return PVMFFailure;
2332                 }
2333 
2334                 iMpeg4File->setDecoderSpecificInfo((uint8*)volHeader.getMemFragPtr(),
2335                                                    (int32)volHeader.getMemFragSize(), trackId);
2336             }
2337             if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_H264_VIDEO_MP4))
2338             {
2339                 iTrackId_H264 = port->GetTrackId();
2340                 iformat_h264 = port->GetFormat();
2341             }
2342             if (port->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT)
2343             {
2344                 iTrackId_Text = port->GetTrackId();
2345                 iformat_text = port->GetFormat();
2346                 OsclRefCounterMemFrag textconfiginfo;
2347 
2348                 if (mediaDataPtr->getFormatSpecificInfo(textconfiginfo) == false ||
2349                         textconfiginfo.getMemFragSize() == 0)
2350                 {
2351                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2352                                     (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - VOL Header not available"));
2353                     return PVMFFailure;
2354                 }
2355                 int32* pVal = (int32*)textconfiginfo.getMemFragPtr();
2356                 iText_sdIndex = *pVal;
2357             }
2358             if (((port->GetFormat() == PVMF_MIME_AMR_IETF) ||
2359                     (port->GetFormat() == PVMF_MIME_AMRWB_IETF)) && mediaDataPtr->getErrorsFlag())
2360             {
2361                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_NOTICE,
2362                                 (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error flag set for AMR!"));
2363                 return PVMFSuccess;
2364             }
2365 
2366             if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_MPEG4_AUDIO))
2367             {
2368                 // Set AAC Config
2369                 OsclRefCounterMemFrag decSpecInfo;
2370                 if (mediaDataPtr->getFormatSpecificInfo(decSpecInfo) == false ||
2371                         decSpecInfo.getMemFragSize() == 0)
2372                 {
2373                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2374                                     (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Decoder Specific not available"));
2375                     return PVMFFailure;
2376                 }
2377 
2378                 iMpeg4File->setDecoderSpecificInfo((uint8*)decSpecInfo.getMemFragPtr(),
2379                                                    (int32)decSpecInfo.getMemFragSize(), trackId);
2380             }
2381 
2382             // Retrieve data from incoming queue
2383             OsclRefCounterMemFrag memFrag;
2384             uint32 numFrags = mediaDataPtr->getNumFragments();
2385             uint32 timestamp = mediaDataPtr->getTimestamp();
2386             iSyncSample = 0;
2387             if (mediaDataPtr->getMarkerInfo()&PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT)
2388             {
2389                 iSyncSample = 1;
2390             }
2391 
2392             Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> pFrame; //vector to store the nals in the particular case of AVC
2393             for (uint32 i = 0; (i < numFrags) && status == PVMFSuccess; i++)
2394             {
2395                 if (!mediaDataPtr->getMediaFragment(i, memFrag))
2396                 {
2397                     status = PVMFFailure;
2398                 }
2399                 else
2400                 {
2401                     OsclMemoryFragment memfragment;
2402                     memfragment.len = memFrag.getMemFragSize();
2403                     memfragment.ptr = memFrag.getMemFragPtr();
2404                     pFrame.push_back(memfragment);
2405                 }
2406             }
2407 
2408 #ifdef ANDROID
2409             if (!iMaxReachedEvent)
2410             {
2411                 // TODO: We are passing port and port->GetFormat(), should pass port only.
2412                 status = iFragmentWriter->enqueueMemFragToTrack(
2413                              pFrame, memFrag, port->GetFormat(), timestamp,
2414                              trackId, (PVMp4FFComposerPort*)aPort);
2415             }
2416             else if (!iMaxReachedReported)
2417             {
2418                 iMaxReachedReported = true;
2419                 ReportInfoEvent(static_cast<PVMFComposerSizeAndDurationEvent>(iMaxReachedEvent), NULL);
2420                 status = PVMFSuccess;
2421             }
2422 #else
2423             status = AddMemFragToTrack(pFrame, memFrag, port->GetFormat(), timestamp,
2424                                        trackId, (PVMp4FFComposerPort*)aPort);
2425 #endif
2426             if (status == PVMFFailure)
2427                 ReportErrorEvent(PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED, (OsclAny*)aPort);
2428         }
2429         break;
2430 
2431         default:
2432             LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Invalid port tag"));
2433             ReportErrorEvent(PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED, (OsclAny*)aPort);
2434             status = PVMFFailure;
2435             break;
2436     }
2437 
2438     return status;
2439 }
2440 
2441 //////////////////////////////////////////////////////////////////////////////////
AddMemFragToTrack(Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> aFrame,OsclRefCounterMemFrag & aMemFrag,PVMFFormatType aFormat,uint32 & aTimestamp,int32 aTrackId,PVMp4FFComposerPort * aPort)2442 PVMFStatus PVMp4FFComposerNode::AddMemFragToTrack(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame, OsclRefCounterMemFrag& aMemFrag,
2443         PVMFFormatType aFormat,
2444         uint32& aTimestamp,
2445         int32 aTrackId,
2446         PVMp4FFComposerPort *aPort)
2447 {
2448     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2449                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: aFormat=%s, aTimestamp=%d, aTrackId=%d",
2450                      aFormat.getMIMEStrPtr(), aTimestamp, aTrackId));
2451 
2452     if (iRealTimeTS)
2453     {
2454         if (iInitTSOffset && (aMemFrag.getMemFragSize() > 0))
2455         {
2456             iTSOffset = aTimestamp;
2457             iInitTSOffset = false;
2458         }
2459 
2460         aTimestamp = aTimestamp - iTSOffset;
2461     }
2462 
2463     uint32 timeScale = 0;
2464     PVMP4FFCNFormatSpecificConfig* config = aPort->GetFormatSpecificConfig();
2465     if (config)
2466     {
2467         timeScale = config->iTimescale;
2468     }
2469 
2470     uint32 i = 0;
2471 #if PROFILING_ON
2472     PVMp4FFCNStats* stats = NULL;
2473     for (i = 0; i < 3; i++)
2474     {
2475         if (aTrackId == iStats[i].iTrackId)
2476         {
2477             stats = &(iStats[i]);
2478             break;
2479         }
2480     }
2481 #endif
2482 
2483     PVMFStatus status = PVMFSuccess;
2484     uint8 flags = 0;
2485     uint32 size = 0;
2486     uint8* data = NULL;
2487     for (i = 0; i < aFrame.size(); i++)
2488     {
2489         size = aFrame[i].len;
2490         data = OSCL_REINTERPRET_CAST(uint8*, aFrame[i].ptr);
2491         if (!data || size == 0)
2492         {
2493             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2494                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - Invalid data or data size"));
2495             return PVMFFailure;
2496         }
2497     }
2498 
2499     if (aFormat == PVMF_MIME_3GPP_TIMEDTEXT ||
2500             aFormat == PVMF_MIME_H264_VIDEO_MP4 ||
2501             aFormat == PVMF_MIME_M4V ||
2502             aFormat == PVMF_MIME_H2631998 ||
2503             aFormat == PVMF_MIME_H2632000)
2504     {
2505         status = CheckMaxDuration(aTimestamp);
2506         if (status == PVMFFailure)
2507         {
2508             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2509                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxDuration failed"));
2510             return status;
2511         }
2512         else if (status == PVMFSuccess)
2513         {
2514             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
2515                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum duration reached"));
2516             return status;
2517         }
2518 
2519         for (i = 0; i < aFrame.size(); i++)
2520         {
2521             size = aFrame[i].len;
2522             status = CheckMaxFileSize(size);
2523             if (status == PVMFFailure)
2524             {
2525                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2526                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxFileSize failed"));
2527                 return status;
2528             }
2529             else if (status == PVMFSuccess)
2530             {
2531                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
2532                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum file size reached"));
2533                 return status;
2534             }
2535 
2536             //No data for some reason.
2537             if (size == 0)
2538             {
2539                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_NOTICE,
2540                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: no data in frag!"));
2541                 return PVMFSuccess;
2542             }
2543         }
2544         uint8 codingType = CODING_TYPE_P;
2545 
2546         if (iRealTimeTS)
2547         {
2548             if (aTimestamp <= aPort->GetLastTS())
2549             {
2550                 aTimestamp = aPort->GetLastTS() + 1;
2551             }
2552 
2553             aPort->SetLastTS(aTimestamp);
2554         }
2555 
2556         //iSyncSample is obtained from the marker info
2557         //to identify the I Frame
2558         if (iSyncSample)
2559         {
2560             codingType = CODING_TYPE_I;
2561         }
2562 
2563         // Format: mtb (1) | layer_id (3) | coding_type (2) | ref_select_code (2)
2564         // flags |= ((stream->iHintTrack.MTB & 0x01) << 7);
2565         // flags |= ((stream->iHintTrack.LayerID & 0x07) << 4);
2566         flags |= ((codingType & 0x03) << 2);
2567         // flags |= (stream->iHintTrack.RefSelCode & 0x03);
2568 
2569         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2570                         (0, "PVMp4FFComposerNode::AddMemFragToTrack: Calling addSampleToTrack(%d, 0x%x, %d, %d, %d)",
2571                          aTrackId, data, size, aTimestamp, flags));
2572 
2573         LOGDATATRAFFIC((0, "PVMp4FFComposerNode::AddMemFragToTrack: TrackID=%d, Size=%d, TS=%d, Flags=%d, Mime=%s",
2574                         aTrackId, size, aTimestamp, flags, aPort->GetMimeType().get_cstr()));
2575 
2576         if (aFormat == PVMF_MIME_3GPP_TIMEDTEXT)
2577         {
2578             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2579                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Calling addtextSampleToTrack(%d, 0x%x, %d, %d, %d)",
2580                              aTrackId, data, size, aTimestamp, flags));
2581             int32 index = iText_sdIndex;
2582 
2583             if (index >= 0)
2584             {
2585 #if PROFILING_ON
2586                 uint32 start = OsclTickCount::TickCount();
2587 #endif
2588                 if (!iMpeg4File->addTextSampleToTrack(aTrackId, aFrame, aTimestamp, flags, index, NULL))
2589                 {
2590                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2591                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addTextSampleToTrack for Timed Text failed"));
2592                     return PVMFFailure;
2593                 }
2594                 iSampleInTrack = true;
2595 #if PROFILING_ON
2596                 uint32 stop = OsclTickCount::TickCount();
2597                 uint32 comptime = OsclTickCount::TicksToMsec(stop - start);
2598                 uint32 dataSize = 0;
2599                 for (uint32 ii = 0; ii < aFrame.size(); ii++)
2600                 {
2601                     dataSize += aFrame[ii].len;
2602                 }
2603                 GenerateDiagnostics(comptime, dataSize);
2604 #endif
2605             }
2606         }
2607         else
2608         {
2609 
2610 #if PROFILING_ON
2611             uint32 start = OsclTickCount::TickCount();
2612 #endif
2613 
2614 #ifdef _TEST_AE_ERROR_HANDLING
2615 
2616             if (1 == iErrorAddSample)
2617             {
2618                 if (iTestFileSize <= iFileSize) //iTestFileSize set in sendProgressReport()
2619                 {
2620                     if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags))
2621                     {
2622                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2623                                         (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed"));
2624                         return PVMFFailure;
2625                     }
2626                 }
2627             }
2628             else if (2 == iErrorAddSample)
2629             {
2630 
2631                 if (aTimestamp <= iFileDuration)
2632                 {
2633                     if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags))
2634                     {
2635                         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2636                                         (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed"));
2637                         return PVMFFailure;
2638                     }
2639                 }
2640             }
2641             else
2642             {
2643                 if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags))
2644                 {
2645                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2646                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed"));
2647                     return PVMFFailure;
2648                 }
2649             }
2650 
2651 #else
2652             if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aTimestamp, flags))
2653             {
2654                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2655                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed"));
2656                 return PVMFFailure;
2657             }
2658 #endif
2659             iSampleInTrack = true;
2660 #ifdef _TEST_AE_ERROR_HANDLING
2661             if (iErrorHandlingAddMemFrag == true)
2662             {
2663                 return PVMFFailure; //Just to trigger error handling
2664             }
2665 #endif
2666 
2667 #if PROFILING_ON
2668             uint32 stop = OsclTickCount::TickCount();
2669             uint32 comptime = OsclTickCount::TicksToMsec(stop - start);
2670             uint32 dataSize = 0;
2671             for (uint32 ii = 0; ii < aFrame.size(); ii++)
2672             {
2673                 dataSize += aFrame[ii].len;
2674             }
2675             GenerateDiagnostics(comptime, dataSize);
2676 #endif
2677         }
2678 
2679 
2680         // Send progress report after sample is successfully added
2681         SendProgressReport(aTimestamp);
2682 
2683 #if PROFILING_ON
2684         ++(stats->iNumFrames);
2685         stats->iDuration = aTimestamp;
2686 #endif
2687     }
2688 
2689     else if ((aFormat == PVMF_MIME_AMR_IETF) ||
2690              (aFormat == PVMF_MIME_AMRWB_IETF))
2691     {
2692         if (iRealTimeTS)
2693         {
2694             if (((int32) aTimestamp - (int32) aPort->GetLastTS()) < 20)
2695             {
2696                 aTimestamp = aPort->GetLastTS() + 20;
2697             }
2698 
2699             aPort->SetLastTS(aTimestamp);
2700         }
2701 
2702         uint32 bytesProcessed = 0;
2703         uint32 frameSize = 0;
2704         Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> amrfrags;
2705         for (i = 0; i < aFrame.size(); i++)
2706         {
2707             bytesProcessed = 0;
2708             size = aFrame[i].len;
2709             data = OSCL_REINTERPRET_CAST(uint8*, aFrame[i].ptr);
2710             // Parse audio data and add one 20ms frame to track at a time
2711             while (bytesProcessed < size)
2712             {
2713                 // Check for max duration
2714                 status = CheckMaxDuration(aTimestamp);
2715                 if (status == PVMFFailure)
2716                 {
2717                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2718                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxDuration failed"));
2719                     return status;
2720                 }
2721                 else if (status == PVMFSuccess)
2722                 {
2723                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
2724                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum duration reached"));
2725                     return status;
2726                 }
2727 
2728                 // Update clock converter
2729                 iClockConverter.set_timescale(timeScale);
2730                 iClockConverter.set_clock_other_timescale(aTimestamp, 1000);
2731 
2732                 // Check max file size
2733                 int32 frSize = GetIETFFrameSize(data[0], aPort->GetCodecType());
2734                 if (frSize == -1)
2735                 {
2736                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2737                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - Frame Type Not Supported - Skipping"));
2738                     LOGDATATRAFFIC((0, "PVMp4FFComposerNode::AddMemFragToTrack - Invalid Frame: TrackID=%d, Byte=0x%x, Mime=%s",
2739                                     aTrackId, data[0], aPort->GetMimeType().get_cstr()));
2740                     return PVMFFailure;
2741                 }
2742                 frameSize = (uint32)frSize;
2743 
2744                 status = CheckMaxFileSize(frameSize);
2745                 if (status == PVMFFailure)
2746                 {
2747                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2748                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxFileSize failed"));
2749                     return status;
2750                 }
2751                 else if (status == PVMFSuccess)
2752                 {
2753                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
2754                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum file size reached"));
2755                     return status;
2756                 }
2757 
2758                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2759                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Calling addSampleToTrack(%d, 0x%x, %d, %d, %d)",
2760                                  aTrackId, data, frameSize, iClockConverter.get_current_timestamp(), flags));
2761 
2762 
2763                 OsclMemoryFragment amr_memfrag;
2764                 amr_memfrag.len = frameSize;
2765                 amr_memfrag.ptr = data;
2766                 amrfrags.push_back(amr_memfrag);
2767 
2768 #if PROFILING_ON
2769                 uint32 start = OsclTickCount::TickCount();
2770 #endif
2771                 uint32 amrts = iClockConverter.get_current_timestamp();
2772 
2773                 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::AddMemFragToTrack: TrackID=%d, Size=%d, TS=%d, Flags=%d, Mime=%s",
2774                                 aTrackId, frameSize, amrts, flags, aPort->GetMimeType().get_cstr()));
2775 
2776                 if (!iMpeg4File->addSampleToTrack(aTrackId, amrfrags, amrts, flags))
2777                 {
2778                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2779                                     (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed"));
2780                     return PVMFFailure;
2781                 }
2782                 iSampleInTrack = true;
2783 #if PROFILING_ON
2784                 uint32 stop = OsclTickCount::TickCount();
2785                 uint32 comptime = OsclTickCount::TicksToMsec(stop - start);
2786                 uint32 dataSize = 0;
2787                 for (uint32 ii = 0; ii < amrfrags.size(); ii++)
2788                 {
2789                     dataSize += amrfrags[ii].len;
2790                 }
2791                 GenerateDiagnostics(comptime, dataSize);
2792 
2793 #endif
2794 
2795                 // Send progress report after sample is successfully added
2796                 SendProgressReport(aTimestamp);
2797 
2798 #if PROFILING_ON
2799                 ++(stats->iNumFrames);
2800                 stats->iDuration = aTimestamp;
2801 #endif
2802                 data += frameSize;
2803                 bytesProcessed += frameSize;
2804                 aTimestamp += 20;
2805                 amrfrags.clear();
2806             }
2807         }
2808         if (iRealTimeTS)
2809         {
2810             aPort->SetLastTS(aTimestamp - 20);
2811         }
2812     }
2813 
2814     else if (aFormat == PVMF_MIME_MPEG4_AUDIO)
2815     {
2816         status = CheckMaxDuration(aTimestamp);
2817         if (status == PVMFFailure)
2818         {
2819             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2820                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxDuration failed"));
2821             return status;
2822         }
2823         else if (status == PVMFSuccess)
2824         {
2825             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
2826                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum duration reached"));
2827             return status;
2828         }
2829 
2830         for (i = 0; i < aFrame.size(); i++)
2831         {
2832             size = aFrame[i].len;
2833             status = CheckMaxFileSize(size);
2834             if (status == PVMFFailure)
2835             {
2836                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2837                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - CheckMaxFileSize failed"));
2838                 return status;
2839             }
2840             else if (status == PVMFSuccess)
2841             {
2842                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_DEBUG,
2843                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: Maxmimum file size reached"));
2844                 return status;
2845             }
2846 
2847             //No data for some reason.
2848             if (size == 0)
2849             {
2850                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_NOTICE,
2851                                 (0, "PVMp4FFComposerNode::AddMemFragToTrack: no data in frag!"));
2852                 return PVMFSuccess;
2853             }
2854         }
2855 
2856         if (iRealTimeTS)
2857         {
2858             if (aTimestamp <= aPort->GetLastTS())
2859             {
2860                 aTimestamp = aPort->GetLastTS() + 1;
2861             }
2862 
2863             aPort->SetLastTS(aTimestamp);
2864         }
2865 
2866         iClockConverter.set_timescale(timeScale);
2867         iClockConverter.set_clock_other_timescale(aTimestamp, 1000);
2868         uint32 aacTS = iClockConverter.get_current_timestamp();
2869 
2870         if (!iMpeg4File->addSampleToTrack(aTrackId, aFrame, aacTS, flags))
2871         {
2872             PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2873                             (0, "PVMp4FFComposerNode::AddMemFragToTrack: Error - addSampleToTrack failed"));
2874             return PVMFFailure;
2875         }
2876         iSampleInTrack = true;
2877         // Send progress report after sample is successfully added
2878         SendProgressReport(aTimestamp);
2879 
2880 #if PROFILING_ON
2881         ++(stats->iNumFrames);
2882         stats->iDuration = aTimestamp;
2883 #endif
2884     }
2885 
2886     return PVMFSuccess;
2887 }
2888 
2889 
GenerateDiagnostics(uint32 aTime,uint32 aSize)2890 void PVMp4FFComposerNode::GenerateDiagnostics(uint32 aTime, uint32 aSize)
2891 {
2892 #if PROFILING_ON
2893     if ((iMinSampleAddTime > aTime) || (0 == iMinSampleAddTime))
2894     {
2895         iMinSampleAddTime = aTime;
2896     }
2897     if (iMaxSampleAddTime < aTime)
2898     {
2899         iMaxSampleAddTime = aTime;
2900     }
2901 
2902     if ((iMinSampleSize > aSize) || (0 == iMinSampleSize))
2903     {
2904         iMinSampleSize = aSize;
2905     }
2906     if (iMaxSampleSize < aSize)
2907     {
2908         iMaxSampleSize = aSize;
2909     }
2910     iNumSamplesAdded++;
2911 #endif
2912     OSCL_UNUSED_ARG(aTime);
2913     OSCL_UNUSED_ARG(aSize);
2914 }
2915 //////////////////////////////////////////////////////////////////////////////////
GetIETFFrameSize(uint8 aFrameType,int32 aCodecType)2916 int32 PVMp4FFComposerNode::GetIETFFrameSize(uint8 aFrameType,
2917         int32 aCodecType)
2918 {
2919     uint8 frameType = (uint8)(aFrameType >> 3) & 0x0f;
2920     if (aCodecType == CODEC_TYPE_AMR_AUDIO)
2921     {
2922         // Find frame size for each frame type
2923         switch (frameType)
2924         {
2925             case 0: // AMR 4.75 Kbps
2926                 return 13;
2927             case 1: // AMR 5.15 Kbps
2928                 return 14;
2929             case 2: // AMR 5.90 Kbps
2930                 return 16;
2931             case 3: // AMR 6.70 Kbps
2932                 return 18;
2933             case 4: // AMR 7.40 Kbps
2934                 return 20;
2935             case 5: // AMR 7.95 Kbps
2936                 return 21;
2937             case 6: // AMR 10.2 Kbps
2938                 return 27;
2939             case 7: // AMR 12.2 Kbps
2940                 return 32;
2941             case 8: // AMR Frame SID
2942                 return 6;
2943             case 9: // AMR Frame GSM EFR SID
2944                 return 7;
2945             case 10:// AMR Frame TDMA EFR SID
2946             case 11:// AMR Frame PDC EFR SID
2947                 return 6;
2948             case 15: // AMR Frame No Data
2949                 return 1;
2950             default: // Error - For Future Use
2951                 return -1;
2952         }
2953     }
2954     else if (aCodecType == CODEC_TYPE_AMR_WB_AUDIO)
2955     {
2956         // Find frame size for each frame type
2957         switch (frameType)
2958         {
2959             case 0: // AMR-WB 6.60 Kbps
2960                 return 18;
2961             case 1: // AMR-WB 8.85 Kbps
2962                 return 24;
2963             case 2: // AMR-WB 12.65 Kbps
2964                 return 33;
2965             case 3: // AMR-WB 14.25 Kbps
2966                 return 37;
2967             case 4: // AMR-WB 15.85 Kbps
2968                 return 41;
2969             case 5: // AMR-WB 18.25 Kbps
2970                 return 47;
2971             case 6: // AMR-WB 19.85 Kbps
2972                 return 51;
2973             case 7: // AMR-WB 23.05 Kbps
2974                 return 59;
2975             case 8: // AMR-WB 23.85 Kbps
2976                 return 61;
2977             case 9: // AMR-WB SID Frame
2978                 return 6;
2979             case 10: //Reserved
2980             case 11: //Reserved
2981             case 12: //Reserved
2982             case 13: //Reserved
2983                 return -1;
2984             case 14: // AMR-WB Frame Lost
2985             case 15: // AMR-WB Frame No Data
2986                 return 1;
2987             default: // Error - For Future Use
2988                 return -1;
2989         }
2990     }
2991     return -1;
2992 }
2993 
2994 //////////////////////////////////////////////////////////////////////////////////
2995 //                 Progress and max size / duration routines
2996 //////////////////////////////////////////////////////////////////////////////////
SendProgressReport(uint32 aTimestamp)2997 PVMFStatus PVMp4FFComposerNode::SendProgressReport(uint32 aTimestamp)
2998 {
2999     if (iDurationReportEnabled &&
3000             aTimestamp >= iNextDurationReport)
3001     {
3002         iNextDurationReport = aTimestamp - (aTimestamp % iDurationReportFreq) + iDurationReportFreq;
3003         ReportInfoEvent(PVMF_COMPOSER_DURATION_PROGRESS, (OsclAny*)aTimestamp);
3004     }
3005     else if (iFileSizeReportEnabled)
3006     {
3007         uint32 metaDataSize = 0;
3008         uint32 mediaDataSize = 0;
3009         uint32 fileSize = 0;
3010 
3011         iMpeg4File->getTargetFileSize(metaDataSize, mediaDataSize);
3012         fileSize = metaDataSize + mediaDataSize;
3013 
3014         if (fileSize >= iNextFileSizeReport)
3015         {
3016             iNextFileSizeReport = fileSize - (fileSize % iFileSizeReportFreq) + iFileSizeReportFreq;
3017             ReportInfoEvent(PVMF_COMPOSER_FILESIZE_PROGRESS, (OsclAny*)fileSize);
3018         }
3019 #ifdef _TEST_AE_ERROR_HANDLING
3020         iTestFileSize = fileSize; //iTestTimeStamp to fail the addSampleTrack() once a particulare time duration is reached as specified in testapp.
3021 #endif
3022     }
3023 
3024     return PVMFSuccess;
3025 }
3026 
3027 //////////////////////////////////////////////////////////////////////////////////
CheckMaxFileSize(uint32 aFrameSize)3028 PVMFStatus PVMp4FFComposerNode::CheckMaxFileSize(uint32 aFrameSize)
3029 {
3030     if (iMaxFileSizeEnabled)
3031     {
3032         uint32 metaDataSize = 0;
3033         uint32 mediaDataSize = 0;
3034         iMpeg4File->getTargetFileSize(metaDataSize, mediaDataSize);
3035 
3036         if ((metaDataSize + mediaDataSize + aFrameSize) >= iMaxFileSize)
3037         {
3038 #ifdef ANDROID
3039             // This code is executed on the fragment writer thread, we
3040             // don't want to call RenderToFile since it will call
3041             // flush() on the writer from this very same
3042             // thread. Instead, we use a marker to report an event to
3043             // the author node next time a new fragment is processed.
3044             iMaxReachedEvent = PVMF_COMPOSER_MAXFILESIZE_REACHED;
3045 #else
3046             // Finalized output file
3047             if (iSampleInTrack)
3048             {
3049                 iSampleInTrack = false;
3050                 if (RenderToFile() != PVMFSuccess)
3051                     return PVMFFailure;
3052             }
3053 
3054             ReportInfoEvent(PVMF_COMPOSER_MAXFILESIZE_REACHED, NULL);
3055             return PVMFSuccess;
3056 #endif
3057         }
3058 
3059         return PVMFPending;
3060     }
3061 
3062     return PVMFErrNotSupported;
3063 }
3064 
3065 //////////////////////////////////////////////////////////////////////////////////
CheckMaxDuration(uint32 aTimestamp)3066 PVMFStatus PVMp4FFComposerNode::CheckMaxDuration(uint32 aTimestamp)
3067 {
3068     //if(!iInfoObserver)
3069     //  return PVMFFailure;
3070 
3071     if (iMaxDurationEnabled)
3072     {
3073         if (aTimestamp >= iMaxTimeDuration)
3074         {
3075 #ifdef ANDROID
3076             // This code is executed on the fragment writer thread, we
3077             // don't want to call RenderToFile since it will call
3078             // flush() on the writer from this very same
3079             // thread. Instead, we use a marker to report an event to
3080             // the author node next time a new fragment is processed.
3081             iMaxReachedEvent = PVMF_COMPOSER_MAXDURATION_REACHED;
3082 #else
3083 
3084             // Finalize output file
3085             if (iSampleInTrack)
3086             {
3087                 iSampleInTrack = false;
3088                 if (RenderToFile() != PVMFSuccess)
3089                     return PVMFFailure;
3090             }
3091 
3092             ReportInfoEvent(PVMF_COMPOSER_MAXDURATION_REACHED, NULL);
3093             return PVMFSuccess;
3094 #endif
3095         }
3096 
3097         return PVMFPending;
3098     }
3099 
3100     return PVMFErrNotSupported;
3101 }
3102 
3103 ////////////////////////////////////////////////////////////////////////////
3104 //                   Event reporting routines.
3105 ////////////////////////////////////////////////////////////////////////////
SetState(TPVMFNodeInterfaceState aState)3106 void PVMp4FFComposerNode::SetState(TPVMFNodeInterfaceState aState)
3107 {
3108     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::SetState: aState=%d", aState));
3109     PVMFNodeInterface::SetState(aState);
3110 }
3111 
ReportErrorEvent(PvmfMp4FFCNError aErrorEvent,OsclAny * aEventData)3112 void PVMp4FFComposerNode::ReportErrorEvent(PvmfMp4FFCNError aErrorEvent, OsclAny* aEventData)
3113 {
3114     LOG_ERR((0, "PVMp4FFComposerNode:ReportErrorEvent: aEventType=%d, aEventData=0x%x", aErrorEvent, aEventData));
3115     switch (aErrorEvent)
3116     {
3117         case PVMF_MP4FFCN_ERROR_FINALIZE_OUTPUT_FILE_FAILED:
3118         case PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED:
3119             PVMFNodeInterface::ReportErrorEvent(PVMFErrResourceConfiguration, aEventData);
3120             break;
3121         default:
3122             PVMFNodeInterface::ReportErrorEvent(PVMFFailure, aEventData);
3123             break;
3124     }
3125 }
3126 
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData)3127 void PVMp4FFComposerNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData)
3128 {
3129     LOG_STACK_TRACE((0, "PVMp4FFComposerNode:ReportInfoEvent: aEventType=%d, aEventData=0x%x", aEventType, aEventData));
3130     PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
3131 }
3132 
3133 
3134 
LogDiagnostics()3135 void PVMp4FFComposerNode::LogDiagnostics()
3136 {
3137 #if PROFILING_ON
3138     oDiagnosticsLogged = true;
3139     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iDiagnosticsLogger, PVLOGMSG_DEBUG, (0, "PVMp4FFComposerNode Stats:Sample Add time (Min:%d, Max:%d), Sample Size(Min:%d, Max:%d), number of samples added:%d\n", iMinSampleAddTime, iMaxSampleAddTime, iMinSampleSize, iMaxSampleSize, iNumSamplesAdded));
3140 #endif
3141 }
3142 
StoreCurrentCommand(PVMp4FFCNCmdQueue & aCurrentCmd,PVMp4FFCNCmd & aCmd,PVMp4FFCNCmdQueue & aCmdQueue)3143 int32 PVMp4FFComposerNode::StoreCurrentCommand(PVMp4FFCNCmdQueue& aCurrentCmd, PVMp4FFCNCmd& aCmd, PVMp4FFCNCmdQueue& aCmdQueue)
3144 {
3145     int32 err = 0;
3146     OSCL_TRY(err, aCurrentCmd.StoreL(aCmd););
3147     OSCL_FIRST_CATCH_ANY(err,
3148                          CommandComplete(aCmdQueue, aCmd, PVMFErrNoMemory);
3149                          return err;
3150                         );
3151     return err;
3152 }
3153