• 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 #ifdef ANDROID
23 // #define LOG_NDEBUG 0
24 #define LOG_TAG "PvMp4Composer"
25 #include <utils/Log.h>
26 #include <utils/Errors.h>
27 #include <utils/threads.h>
28 #endif // ANDROID
29 
30 #ifndef PVMP4FFCN_NODE_H_INCLUDED
31 #include "pvmp4ffcn_node.h"
32 #endif
33 #ifndef PVMP4FFCN_FACTORY_H_INCLUDED
34 #include "pvmp4ffcn_factory.h"
35 #endif
36 #ifndef PVMP4FFCN_PORT_H_INCLUDED
37 #include "pvmp4ffcn_port.h"
38 #endif
39 #ifndef OSCL_DLL_H_INCLUDED
40 #include "oscl_dll.h"
41 #endif
42 #ifndef OSCL_MEM_BASIC_FUNCTIONS_H
43 #include "oscl_mem_basic_functions.h"
44 #endif
45 #include "pvmf_omx_basedec_node.h"  // for NUMBER_OUTPUT_BUFFER
46 
47 #ifdef ANDROID
48 namespace android
49 {
50 
51 // FragmentWriter is a queue of media fragment to be written in the
52 // media file. The caller enqueues the next fragment and returns
53 // immediately. An separate thread dequeues the fragment and writes it.
54 //
55 // This class is friend with the composer node it belongs to, in order
56 // to be able to call the original AddMemFragToTrack which does all
57 // the work.
58 //
59 // The queue is implemented using a circular buffer. mBuffer is the
60 // start of the array and mEnd points just after the last element in
61 // the array.
62 // mFirst points to the oldest fragment.
63 // mLast points to the next available cell for a new fragment.
64 // When the array is empty or full mFirst == mLast.
65 
66 class FragmentWriter: public Thread
67 {
68     public:
FragmentWriter(PVMp4FFComposerNode * composer)69         FragmentWriter(PVMp4FFComposerNode *composer) :
70                 Thread(kThreadCallJava), mSize(0), mEnd(mBuffer + kCapacity),
71                 mFirst(mBuffer), mLast(mBuffer), mComposer(composer),
72                 mPrevWriteStatus(PVMFSuccess), mTid(NULL), mDropped(0), mExitRequested(false) {}
73 
~FragmentWriter()74         virtual ~FragmentWriter()
75         {
76             Mutex::Autolock l(mRequestMutex);
77             LOG_ASSERT(0 == mSize, "The queue should be empty by now.");
78             LOG_ASSERT(mExitRequested, "Deleting an active instance.");
79             LOGD_IF(0 < mSize, "Flushing %d frags in dtor", mSize);
80             while (0 < mSize)  // make sure we are flushed
81             {
82                 decrPendingRequests();
83             }
84         }
85 
86         // Mark the thread as exiting and kick it so it can see the
87         // exitPending state.
requestExit()88         virtual void requestExit()
89         {
90             mExitRequested = true;
91             Thread::requestExit();
92             mRequestMutex.lock();
93             mRequestCv.signal();
94             mRequestMutex.unlock();
95         }
96 
97         // Wait for all the fragment to be written.
flush()98         virtual void flush()
99         {
100             LOG_ASSERT(androidGetThreadId() != mTid, "Reentrant call");
101 
102             bool done = false;
103             size_t iter = 0;
104             while (!done)
105             {
106                 mRequestMutex.lock();
107                 done = mSize == 0 || iter > kMaxFlushAttempts;
108                 if (!done) mRequestCv.signal();
109                 mRequestMutex.unlock();
110                 if (!done) usleep(kFlushSleepMicros);
111                 ++iter;
112             }
113             LOG_ASSERT(iter <= kMaxFlushAttempts, "Failed to flush");
114         }
115 
116         // Called by the ProcessIncomingMsg method from the
117         // PVMp4FFComposerNode to append the fragment to the track.
118         // @return The result of the *previous* fragment written. Since the call
119         //         is asynch we cannot wait.
enqueueMemFragToTrack(Oscl_Vector<OsclMemoryFragment,OsclMemAllocator> aFrame,OsclRefCounterMemFrag & aMemFrag,PVMFFormatType aFormat,uint32 & aTimestamp,int32 aTrackId,PVMp4FFComposerPort * aPort)120         PVMFStatus enqueueMemFragToTrack(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame,
121                                          OsclRefCounterMemFrag& aMemFrag, PVMFFormatType aFormat,
122                                          uint32& aTimestamp, int32 aTrackId, PVMp4FFComposerPort *aPort)
123         {
124             if (mExitRequested) return PVMFErrCancelled;
125             Mutex::Autolock lock(mRequestMutex);
126 
127             // When the queue is full, we drop the request. This frees the
128             // memory fragment and keeps the system running. Decoders are
129             // unhappy when there is no buffer available to write the
130             // output.
131             // An alternative would be to discard the oldest fragment
132             // enqueued to free some space. However that would modify
133             // mFirst and require extra locking because the thread maybe
134             // in the process of writing it.
135             if (mSize == kCapacity)
136             {
137                 ++mDropped;
138                 LOGW_IF((mDropped % kLogDroppedPeriod) == 0, "Frame %d dropped.", mDropped);
139                 // TODO: Should we return an error code here?
140                 return mPrevWriteStatus;
141             }
142 
143             mLast->set(aFrame, aMemFrag, aFormat, aTimestamp, aTrackId, aPort);
144             incrPendingRequests();
145 
146             mRequestCv.signal();
147             return mPrevWriteStatus;
148         }
149 
150     private:
151         static const bool kThreadCallJava = false;
152         static const size_t kLogDroppedPeriod = 10;  // Arbitrary.
153         // Must match the number of buffers allocated in the decoder.
154         static const size_t kCapacity = NUMBER_OUTPUT_BUFFER;
155         static const size_t kWarningThreshold = kCapacity * 3 / 4; // Warn at 75%
156         static const OsclRefCounterMemFrag kEmptyFrag;
157         // Flush blocks for 2 seconds max.
158         static const size_t kMaxFlushAttempts = 10;
159         static const int kFlushSleepMicros = 200 * 1000;
160 
161         struct Request
162         {
setandroid::FragmentWriter::Request163             void set(Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> aFrame,
164                      OsclRefCounterMemFrag& aMemFrag, PVMFFormatType aFormat,
165                      uint32 aTimestamp, int32 aTrackId, PVMp4FFComposerPort *aPort)
166             {
167                 mFrame = aFrame;
168                 mFrag = aMemFrag;
169                 mFormat = aFormat;
170                 mTimestamp = aTimestamp;
171                 mTrackId = aTrackId;
172                 mPort = aPort;
173             }
174 
175             Oscl_Vector<OsclMemoryFragment, OsclMemAllocator> mFrame;
176             OsclRefCounterMemFrag mFrag;
177             PVMFFormatType mFormat;
178             uint32 mTimestamp;
179             uint32 mTrackId;
180             PVMp4FFComposerPort *mPort;
181         };
182 
incrPendingRequests()183         void incrPendingRequests()
184         {
185             ++mLast;
186             if (mEnd == mLast) mLast = mBuffer;
187             ++mSize;
188         }
189 
decrPendingRequests()190         void decrPendingRequests()
191         {
192             mFirst->mFrame.clear();
193             // Release the memory fragment tracked using a refcount
194             // class. Need to assign an empty frag to release the memory
195             // fragment. We cannot wait for the array to wrap around.
196             mFirst->mFrag = kEmptyFrag;  // FIXME: This assignement to decr the ref count is ugly.
197             ++mFirst;
198             if (mEnd == mFirst) mFirst = mBuffer;
199             --mSize;
200         }
201 
202         // Called by the base class Thread.
203         // @return true if there more work to do. false when done.
204         // @Override Thread
threadLoop()205         virtual bool threadLoop()
206         {
207             if (!mTid) mTid = androidGetThreadId();
208 
209             LOG_ASSERT(androidGetThreadId() == mTid,
210                        "Thread id has changed!: %p != %p", mTid, androidGetThreadId());
211 
212             size_t numFrags = 0;
213             // Check if there's work to do. Otherwise wait for new fragment.
214             mRequestMutex.lock();
215             numFrags = mSize;
216             mRequestMutex.unlock();
217 
218             bool doneWaiting = numFrags != 0;
219             while (!doneWaiting)
220             {
221                 mRequestMutex.lock();
222                 mRequestCv.wait(mRequestMutex);
223                 doneWaiting = mSize > 0 || mExitRequested;
224                 numFrags = mSize;
225                 mRequestMutex.unlock();
226             }
227 
228             if (mExitRequested) return false;
229 
230             LOGW_IF(numFrags > kWarningThreshold, "%d fragments in queue.", numFrags);
231             for (size_t i = 0; i < numFrags; ++i)
232             {
233                 // Don't lock the array while we are calling
234                 // AddMemFragToTrack, which may last a long time, because
235                 // we are the only thread accessing mFirst.
236                 mPrevWriteStatus = mComposer->AddMemFragToTrack(
237                                        mFirst->mFrame, mFirst->mFrag, mFirst->mFormat,
238                                        mFirst->mTimestamp, mFirst->mTrackId, mFirst->mPort);
239 
240                 mRequestMutex.lock();
241                 decrPendingRequests();
242                 mRequestMutex.unlock();
243             }
244             return true;
245         }
246 
247 
248         Mutex mRequestMutex;  // Protects mRequestCv, mBuffer, mFirst, mLast, mDropped
249         Condition mRequestCv;
250         Request mBuffer[kCapacity];
251         size_t mSize;
252         void *const mEnd;  // Marker for the end of the array.
253         Request *mFirst, *mLast;
254 
255         // mComposer with the real implementation of the AddMemFragToTrack method.
256         PVMp4FFComposerNode *mComposer;
257         // TODO: lock needed for mPrevWriteStatus? Are int assignement atomic on arm?
258         PVMFStatus mPrevWriteStatus;
259 
260         android_thread_id_t mTid;
261         size_t mDropped;
262         // Unlike exitPending(), stays to true once exit has been called.
263         bool mExitRequested;
264 };
265 const OsclRefCounterMemFrag FragmentWriter::kEmptyFrag;
266 }
267 #endif // ANDROID
268 
269 #define LOG_STACK_TRACE(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, m);
270 #define LOG_DEBUG(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG, m);
271 #define LOG_ERR(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iLogger,PVLOGMSG_ERR,m);
272 #define LOGDATATRAFFIC(m) PVLOGGER_LOGMSG(PVLOGMSG_INST_REL,iDataPathLogger,PVLOGMSG_INFO,m);
273 
274 #ifdef _TEST_AE_ERROR_HANDLING
275 const uint32 FAIL_NODE_CMD_START = 2;
276 const uint32 FAIL_NODE_CMD_STOP = 3;
277 const uint32 FAIL_NODE_CMD_FLUSH = 4;
278 const uint32 FAIL_NODE_CMD_PAUSE = 5;
279 const uint32 FAIL_NODE_CMD_RELEASE_PORT = 7;
280 #endif
281 
282 #define SLASH '/'
283 
284 #define LANG_CODE_SIZE 3
285 
286 // Define entry point for this DLL
OSCL_DLL_ENTRY_POINT_DEFAULT()287 OSCL_DLL_ENTRY_POINT_DEFAULT()
288 
289 
290 
291 ////////////////////////////////////////////////////////////////////////////
292 OSCL_EXPORT_REF PVMFNodeInterface* PVMp4FFComposerNodeFactory::CreateMp4FFComposer(int32 aPriority)
293 {
294     int32 err = 0;
295     PVMFNodeInterface* node = NULL;
296 
297     OSCL_TRY(err,
298              node = (PVMFNodeInterface*)OSCL_NEW(PVMp4FFComposerNode, (aPriority));
299              if (!node)
300              OSCL_LEAVE(OsclErrNoMemory);
301             );
302 
303     OSCL_FIRST_CATCH_ANY(err, return NULL;);
304     return node;
305 }
306 
307 ////////////////////////////////////////////////////////////////////////////
DeleteMp4FFComposer(PVMFNodeInterface * aComposer)308 OSCL_EXPORT_REF bool PVMp4FFComposerNodeFactory::DeleteMp4FFComposer(PVMFNodeInterface* aComposer)
309 {
310     if (aComposer)
311     {
312         PVMp4FFComposerNode* node = (PVMp4FFComposerNode*)aComposer;
313         OSCL_DELETE(node);
314         return true;
315     }
316 
317     return false;
318 }
319 
320 ////////////////////////////////////////////////////////////////////////////
PVMp4FFComposerNode(int32 aPriority)321 PVMp4FFComposerNode::PVMp4FFComposerNode(int32 aPriority)
322         : OsclActiveObject(aPriority, "PVMp4FFComposerNode")
323         , iMpeg4File(NULL)
324         , iFileType(0)
325         , iAuthoringMode(PVMP4FF_3GPP_DOWNLOAD_MODE)
326         , iPresentationTimescale(1000)
327         , iMovieFragmentDuration(2000)
328         , iRecordingYear(0)
329         , iClockConverter(8000)
330         , iExtensionRefCount(0)
331         , iRealTimeTS(false)
332         , iInitTSOffset(false)
333         , iTSOffset(0)
334         , iMaxFileSizeEnabled(false)
335         , iMaxDurationEnabled(false)
336         , iMaxFileSize(0)
337         , iMaxTimeDuration(0)
338         , iFileSizeReportEnabled(false)
339         , iDurationReportEnabled(false)
340         , iFileSizeReportFreq(0)
341         , iDurationReportFreq(0)
342         , iNextDurationReport(0)
343         , iNextFileSizeReport(0)
344         , iCacheSize(0)
345         , iConfigSize(0)
346         , pConfig(NULL)
347         , iTrackId_H264(0)
348         , iTrackId_Text(0)
349         , iSyncSample(0)
350         , iformat_h264(PVMF_MIME_FORMAT_UNKNOWN)
351         , iformat_text(PVMF_MIME_FORMAT_UNKNOWN)
352         , iNodeEndOfDataReached(false)
353         , iSampleInTrack(false)
354         , iFileRendered(false)
355 {
356     iInterfaceState = EPVMFNodeCreated;
357     iNum_PPS_Set = 0;
358     iNum_SPS_Set = 0;
359     iText_sdIndex = 0;
360     iFileObject = NULL;
361 #if PROFILING_ON
362     iMaxSampleAddTime = 0;
363     iMinSampleAddTime = 0;
364     iMinSampleSize = 0;
365     iMaxSampleSize = 0;
366     iNumSamplesAdded = 0;
367     oDiagnosticsLogged = false;
368     iDiagnosticsLogger = PVLogger::GetLoggerObject("pvauthordiagnostics.composer.mp4");
369     // Statistics
370     for (uint32 i = 0; i < 3; i++)
371         oscl_memset(&(iStats[i]), 0, sizeof(PVMp4FFCNStats));
372 #endif
373 
374     iLogger = PVLogger::GetLoggerObject("PVMp4FFComposerNode");
375     iDataPathLogger = PVLogger::GetLoggerObject("datapath.sinknode.mp4composer");
376     int32 err;
377     OSCL_TRY(err,
378              //Create the input command queue.  Use a reserve to avoid lots of
379              //dynamic memory allocation.
380              iCmdQueue.Construct(PVMF_MP4FFCN_COMMAND_ID_START, PVMF_MP4FFCN_COMMAND_VECTOR_RESERVE);
381              iCurrentCmd.Construct(0, 1); // There's only 1 current command
382 
383 
384              //Create the port vector.
385              iInPorts.Construct(PVMF_MP4FFCN_PORT_VECTOR_RESERVE);
386             );
387 
388     OSCL_FIRST_CATCH_ANY(err,
389                          //if a leave happened, cleanup and re-throw the error
390                          iCmdQueue.clear();
391                          iCurrentCmd.clear();
392                          iInPorts.clear();
393                          memvector_sps.clear();
394                          memvector_pps.clear();
395                          OSCL_CLEANUP_BASE_CLASS(PVMFNodeInterface);
396                          OSCL_CLEANUP_BASE_CLASS(OsclActiveObject);
397                          OSCL_LEAVE(err);
398                         );
399 
400 #ifdef ANDROID
401     iMaxReachedEvent = 0;
402     iMaxReachedReported = false;
403     iFragmentWriter = new android::FragmentWriter(this);
404     iFragmentWriter->run(LOG_TAG);
405 #endif
406 
407 #ifdef _TEST_AE_ERROR_HANDLING
408     iErrorHandlingAddMemFrag = false;
409     iErrorHandlingAddTrack = false;
410     iErrorCreateComposer = false;
411     iErrorRenderToFile = false;
412     iErrorAddTrack = PVMF_MIME_FORMAT_UNKNOWN;
413     iErrorNodeCmd = 0;
414     iTestFileSize = 0;
415     iTestTimeStamp = 0;
416     iErrorAddSample = 0;
417     iFileSize = 0;
418     iFileDuration = 0;
419     iErrorDataPathStall = 0;
420 #endif
421 }
422 
423 ////////////////////////////////////////////////////////////////////////////
~PVMp4FFComposerNode()424 PVMp4FFComposerNode::~PVMp4FFComposerNode()
425 {
426 #if PROFILING_ON
427     if (!oDiagnosticsLogged)
428     {
429         LogDiagnostics();
430     }
431 #endif
432 
433 #ifdef ANDROID
434     if (iFragmentWriter != NULL)
435     {
436         iFragmentWriter->requestExit(); // kick the thread
437         iFragmentWriter->requestExitAndWait();
438     }
439 #endif
440 
441     if (iMpeg4File)
442     {
443         PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
444 
445         if (!iFileRendered)
446         {
447             iFs.Connect();
448             iFs.Oscl_DeleteFile(iFileName.get_cstr());
449             iFs.Close();
450         }
451     }
452     if (iFileObject)
453     {
454         iFileObject->Close();
455         OSCL_DELETE(iFileObject);
456         iFileObject = NULL;
457     }
458     for (uint32 i = 0; i < iKeyWordVector.size() ; i++)
459     {
460         if (iKeyWordVector[i] != NULL)
461         {
462             OSCL_DELETE(iKeyWordVector[i]);
463             iKeyWordVector[i] = NULL;
464         }
465 
466     }
467 
468     if (pConfig != NULL)
469     {
470         OSCL_FREE(pConfig);
471         iConfigSize = 0;
472     }
473 
474     if (iLocationInfo._location_name != NULL)
475     {
476         OSCL_FREE(iLocationInfo._location_name);
477     }
478 
479     if (iLocationInfo._astronomical_body != NULL)
480     {
481         OSCL_FREE(iLocationInfo._astronomical_body);
482     }
483 
484     if (iLocationInfo._additional_notes != NULL)
485     {
486         OSCL_FREE(iLocationInfo._additional_notes);
487     }
488     // Cleanup allocated ports
489     while (!iInPorts.empty())
490     {
491         iInPorts.Erase(&iInPorts.front());
492 
493     }
494     //Cleanup commands
495     //The command queues are self-deleting, but we want to
496     //notify the observer of unprocessed commands.
497     while (!iCmdQueue.empty())
498     {
499         CommandComplete(iCmdQueue, iCmdQueue[0], PVMFFailure);
500     }
501 
502     while (!iCurrentCmd.empty())
503     {
504         CommandComplete(iCurrentCmd, iCurrentCmd[0], PVMFFailure);
505     }
506     iNodeEndOfDataReached = false;
507 
508     Cancel();
509     if (iInterfaceState != EPVMFNodeCreated)
510         iInterfaceState = EPVMFNodeIdle;
511 
512 }
513 
514 ////////////////////////////////////////////////////////////////////////////
ThreadLogon()515 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::ThreadLogon()
516 {
517     switch (iInterfaceState)
518     {
519         case EPVMFNodeCreated:
520             if (!IsAdded())
521                 AddToScheduler();
522             SetState(EPVMFNodeIdle);
523             return PVMFSuccess;
524         default:
525             return PVMFErrInvalidState;
526     }
527 }
528 
529 ////////////////////////////////////////////////////////////////////////////
ThreadLogoff()530 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::ThreadLogoff()
531 {
532     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMp4FFComposerNode:ThreadLogoff"));
533     switch (iInterfaceState)
534     {
535         case EPVMFNodeIdle:
536             if (IsAdded())
537                 RemoveFromScheduler();
538             iLogger = NULL;
539             iDataPathLogger = NULL;
540             SetState(EPVMFNodeCreated);
541             return PVMFSuccess;
542 
543         default:
544             return PVMFErrInvalidState;
545     }
546 }
547 
548 ////////////////////////////////////////////////////////////////////////////
GetCapability(PVMFNodeCapability & aNodeCapability)549 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::GetCapability(PVMFNodeCapability& aNodeCapability)
550 {
551     aNodeCapability.iCanSupportMultipleInputPorts = true;
552     aNodeCapability.iCanSupportMultipleOutputPorts = false;
553     aNodeCapability.iHasMaxNumberOfPorts = true;
554     aNodeCapability.iMaxNumberOfPorts = PVMF_MP4FFCN_MAX_INPUT_PORT + PVMF_MP4FFCN_MAX_OUTPUT_PORT;
555     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_M4V);
556     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H264_VIDEO_MP4);
557     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H2631998);
558     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_H2632000);
559     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IETF);
560     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF);
561     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_3GPP_TIMEDTEXT);
562     aNodeCapability.iInputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO);
563     return PVMFSuccess;
564 }
565 
566 ////////////////////////////////////////////////////////////////////////////
GetPorts(const PVMFPortFilter * aFilter)567 OSCL_EXPORT_REF PVMFPortIter* PVMp4FFComposerNode::GetPorts(const PVMFPortFilter* aFilter)
568 {
569     OSCL_UNUSED_ARG(aFilter);
570     iInPorts.Reset();
571     return &iInPorts;
572 }
573 
574 ////////////////////////////////////////////////////////////////////////////
QueryUUID(PVMFSessionId aSession,const PvmfMimeString & aMimeType,Oscl_Vector<PVUuid,OsclMemAllocator> & aUuids,bool aExactUuidsOnly,const OsclAny * aContext)575 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::QueryUUID(PVMFSessionId aSession, const PvmfMimeString& aMimeType,
576         Oscl_Vector<PVUuid, OsclMemAllocator>& aUuids,
577         bool aExactUuidsOnly, const OsclAny* aContext)
578 {
579     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::QueryUUID"));
580 
581     PVMp4FFCNCmd cmd;
582     cmd.Construct(aSession, PVMF_GENERIC_NODE_QUERYUUID, aMimeType, aUuids, aExactUuidsOnly, aContext);
583     return QueueCommandL(cmd);
584 }
585 
586 ////////////////////////////////////////////////////////////////////////////
QueryInterface(PVMFSessionId aSession,const PVUuid & aUuid,PVInterface * & aInterfacePtr,const OsclAny * aContext)587 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::QueryInterface(PVMFSessionId aSession, const PVUuid& aUuid,
588         PVInterface*& aInterfacePtr,
589         const OsclAny* aContext)
590 {
591     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
592                     (0, "PVMp4FFComposerNode::QueryInterface"));
593     PVMp4FFCNCmd cmd;
594     cmd.Construct(aSession, PVMF_GENERIC_NODE_QUERYINTERFACE, aUuid, aInterfacePtr, aContext);
595     return QueueCommandL(cmd);
596 }
597 
598 ////////////////////////////////////////////////////////////////////////////
Init(PVMFSessionId aSession,const OsclAny * aContext)599 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Init(PVMFSessionId aSession, const OsclAny* aContext)
600 {
601     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Init"));
602     PVMp4FFCNCmd cmd;
603     cmd.Construct(aSession, PVMF_GENERIC_NODE_INIT, aContext);
604     return QueueCommandL(cmd);
605 }
606 
607 ////////////////////////////////////////////////////////////////////////////
Prepare(PVMFSessionId aSession,const OsclAny * aContext)608 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Prepare(PVMFSessionId aSession, const OsclAny* aContext)
609 {
610     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Prepare"));
611     PVMp4FFCNCmd cmd;
612     cmd.Construct(aSession, PVMF_GENERIC_NODE_PREPARE, aContext);
613     return QueueCommandL(cmd);
614 }
615 
616 ////////////////////////////////////////////////////////////////////////////
RequestPort(PVMFSessionId aSession,int32 aPortTag,const PvmfMimeString * aPortConfig,const OsclAny * aContext)617 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::RequestPort(PVMFSessionId aSession,
618         int32 aPortTag,
619         const PvmfMimeString* aPortConfig,
620         const OsclAny* aContext)
621 {
622     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::RequestPort"));
623     PVMp4FFCNCmd cmd;
624     cmd.Construct(aSession, PVMF_GENERIC_NODE_REQUESTPORT, aPortTag, aPortConfig, aContext);
625     return QueueCommandL(cmd);
626 }
627 
628 ////////////////////////////////////////////////////////////////////////////
ReleasePort(PVMFSessionId aSession,PVMFPortInterface & aPort,const OsclAny * aContext)629 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::ReleasePort(PVMFSessionId aSession,
630         PVMFPortInterface& aPort,
631         const OsclAny* aContext)
632 {
633     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::ReleasePort"));
634     PVMp4FFCNCmd cmd;
635     cmd.Construct(aSession, PVMF_GENERIC_NODE_RELEASEPORT, aPort, aContext);
636     return QueueCommandL(cmd);
637 }
638 
639 ////////////////////////////////////////////////////////////////////////////
Start(PVMFSessionId aSession,const OsclAny * aContext)640 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Start(PVMFSessionId aSession, const OsclAny* aContext)
641 {
642     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Start"));
643     PVMp4FFCNCmd cmd;
644     cmd.Construct(aSession, PVMF_GENERIC_NODE_START, aContext);
645     return QueueCommandL(cmd);
646 }
647 
648 ////////////////////////////////////////////////////////////////////////////
Stop(PVMFSessionId aSession,const OsclAny * aContext)649 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Stop(PVMFSessionId aSession, const OsclAny* aContext)
650 {
651     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Stop"));
652     PVMp4FFCNCmd cmd;
653     cmd.Construct(aSession, PVMF_GENERIC_NODE_STOP, aContext);
654     return QueueCommandL(cmd);
655 }
656 
657 ////////////////////////////////////////////////////////////////////////////
Pause(PVMFSessionId aSession,const OsclAny * aContext)658 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Pause(PVMFSessionId aSession, const OsclAny* aContext)
659 {
660     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Pause"));
661     PVMp4FFCNCmd cmd;
662     cmd.Construct(aSession, PVMF_GENERIC_NODE_PAUSE, aContext);
663     return QueueCommandL(cmd);
664 }
665 
Flush(PVMFSessionId aSession,const OsclAny * aContext)666 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Flush(PVMFSessionId aSession, const OsclAny* aContext)
667 {
668     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Flush"));
669     PVMp4FFCNCmd cmd;
670     cmd.Construct(aSession, PVMF_GENERIC_NODE_FLUSH, aContext);
671     return QueueCommandL(cmd);
672 }
673 
674 ////////////////////////////////////////////////////////////////////////////
Reset(PVMFSessionId aSession,const OsclAny * aContext)675 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::Reset(PVMFSessionId aSession, const OsclAny* aContext)
676 {
677     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::Reset"));
678     PVMp4FFCNCmd cmd;
679     cmd.Construct(aSession, PVMF_GENERIC_NODE_RESET, aContext);
680     return QueueCommandL(cmd);
681 }
682 
683 ////////////////////////////////////////////////////////////////////////////
CancelAllCommands(PVMFSessionId aSession,const OsclAny * aContext)684 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::CancelAllCommands(PVMFSessionId aSession, const OsclAny* aContext)
685 {
686     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::CancelAllCommands"));
687     PVMp4FFCNCmd cmd;
688     cmd.Construct(aSession, PVMF_GENERIC_NODE_CANCELALLCOMMANDS, aContext);
689     return QueueCommandL(cmd);
690 }
691 
692 ////////////////////////////////////////////////////////////////////////////
CancelCommand(PVMFSessionId aSession,PVMFCommandId aCmdId,const OsclAny * aContext)693 OSCL_EXPORT_REF PVMFCommandId PVMp4FFComposerNode::CancelCommand(PVMFSessionId aSession, PVMFCommandId aCmdId, const OsclAny* aContext)
694 {
695     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::CancelCommand"));
696     PVMp4FFCNCmd cmd;
697     cmd.Construct(aSession, PVMF_GENERIC_NODE_CANCELCOMMAND, aCmdId, aContext);
698     return QueueCommandL(cmd);
699 }
700 
701 ////////////////////////////////////////////////////////////////////////////
addRef()702 OSCL_EXPORT_REF void PVMp4FFComposerNode::addRef()
703 {
704     ++iExtensionRefCount;
705 }
706 
707 ////////////////////////////////////////////////////////////////////////////
removeRef()708 OSCL_EXPORT_REF void PVMp4FFComposerNode::removeRef()
709 {
710     if (iExtensionRefCount > 0)
711         --iExtensionRefCount;
712 }
713 
714 ////////////////////////////////////////////////////////////////////////////
queryInterface(const PVUuid & uuid,PVInterface * & iface)715 OSCL_EXPORT_REF bool PVMp4FFComposerNode::queryInterface(const PVUuid& uuid, PVInterface*& iface)
716 {
717     if (uuid == KPVMp4FFCNClipConfigUuid)
718     {
719         PVMp4FFCNClipConfigInterface* myInterface = OSCL_STATIC_CAST(PVMp4FFCNClipConfigInterface*, this);
720         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
721         ++iExtensionRefCount;
722     }
723     else if (uuid == KPVMp4FFCNTrackConfigUuid)
724     {
725         PVMp4FFCNTrackConfigInterface* myInterface = OSCL_STATIC_CAST(PVMp4FFCNTrackConfigInterface*, this);
726         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
727         ++iExtensionRefCount;
728     }
729     else if (uuid == PvmfComposerSizeAndDurationUuid)
730     {
731         PvmfComposerSizeAndDurationInterface* myInterface = OSCL_STATIC_CAST(PvmfComposerSizeAndDurationInterface*, this);
732         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
733         ++iExtensionRefCount;
734     }
735     else if (uuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
736     {
737         PvmiCapabilityAndConfig* myInterface = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, this);
738         iface = OSCL_STATIC_CAST(PVInterface*, myInterface);
739         ++iExtensionRefCount;
740     }
741     else
742     {
743         iface = NULL;
744         return false;
745     }
746 
747     return true;
748 }
749 
750 ////////////////////////////////////////////////////////////////////////////
751 //            PVMp4FFCNClipConfigInterface routines
752 ////////////////////////////////////////////////////////////////////////////
ConvertLangCode(const OSCL_String & aLang)753 OSCL_EXPORT_REF uint16 PVMp4FFComposerNode::ConvertLangCode(const OSCL_String & aLang)
754 {
755     int i = 0;
756     char lang[LANG_CODE_SIZE] = {0};
757     oscl_strncpy(lang, aLang.get_cstr(), LANG_CODE_SIZE);
758 
759     uint16 lang_code = ((((uint16)lang[i] - 0x60) << 10) | (((uint16)lang[i+1] - 0x60) << 5) | ((uint16)lang[i+2] - 0x60));
760 
761     return lang_code;
762 }
763 /////////////////////////////////////////////////////////////////////////////
SetOutputFileName(const OSCL_wString & aFileName)764 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileName(const OSCL_wString& aFileName)
765 {
766     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
767         return false;
768 
769     iFileName = aFileName;
770     return PVMFSuccess;
771 }
772 //////////////////////////////////////////////////////////////////////////////
SetOutputFileDescriptor(const OsclFileHandle * aFileHandle)773 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetOutputFileDescriptor(const OsclFileHandle* aFileHandle)
774 {
775     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
776         return false;
777 
778     iFileObject = OSCL_NEW(Oscl_File, (0, (OsclFileHandle *)aFileHandle));
779     iFileObject->SetPVCacheSize(0);
780     iFileObject->SetAsyncReadBufferSize(0);
781     iFileObject->SetNativeBufferSize(0);
782     iFileObject->SetLoggingEnable(false);
783     iFileObject->SetSummaryStatsLoggingEnable(false);
784     iFileObject->SetFileHandle((OsclFileHandle*)aFileHandle);
785 
786     //call open
787     int32 retval = iFileObject->Open(_STRLIT_CHAR("dummy"),
788                                      Oscl_File::MODE_READWRITE | Oscl_File::MODE_BINARY,
789                                      iFs);
790 
791     if (retval == 0)
792     {
793         return PVMFSuccess;
794     }
795     return PVMFFailure;
796 }
797 ////////////////////////////////////////////////////////////////////////////
SetAuthoringMode(PVMp4FFCN_AuthoringMode aAuthoringMode)798 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAuthoringMode(PVMp4FFCN_AuthoringMode aAuthoringMode)
799 {
800     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
801         return PVMFErrInvalidState;
802 
803     iAuthoringMode = aAuthoringMode;
804     return PVMFSuccess;
805 }
806 
807 ////////////////////////////////////////////////////////////////////////////
SetPresentationTimescale(uint32 aTimescale)808 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetPresentationTimescale(uint32 aTimescale)
809 {
810     if (iInterfaceState != EPVMFNodeIdle &&
811             iInterfaceState != EPVMFNodeInitialized &&
812             iInterfaceState != EPVMFNodePrepared)
813         return PVMFErrInvalidState;
814 
815     iPresentationTimescale = aTimescale;
816     return PVMFSuccess;
817 }
818 
819 ////////////////////////////////////////////////////////////////////////////
SetVersion(const OSCL_wString & aVersion,const OSCL_String & aLangCode)820 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetVersion(const OSCL_wString& aVersion, const OSCL_String& aLangCode)
821 {
822     if (iInterfaceState != EPVMFNodeIdle &&
823             iInterfaceState != EPVMFNodeInitialized &&
824             iInterfaceState != EPVMFNodePrepared)
825         return PVMFErrInvalidState;
826 
827     iVersion.iDataString = aVersion;
828     iVersion.iLangCode = ConvertLangCode(aLangCode);
829     return PVMFSuccess;
830 }
831 
832 ////////////////////////////////////////////////////////////////////////////
SetTitle(const OSCL_wString & aTitle,const OSCL_String & aLangCode)833 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetTitle(const OSCL_wString& aTitle, const OSCL_String& aLangCode)
834 {
835     if (iInterfaceState != EPVMFNodeIdle &&
836             iInterfaceState != EPVMFNodeInitialized &&
837             iInterfaceState != EPVMFNodePrepared)
838         return PVMFErrInvalidState;
839 
840     iTitle.iDataString = aTitle;
841     iTitle.iLangCode = ConvertLangCode(aLangCode);
842     return PVMFSuccess;
843 }
844 
845 ////////////////////////////////////////////////////////////////////////////
SetAuthor(const OSCL_wString & aAuthor,const OSCL_String & aLangCode)846 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAuthor(const OSCL_wString& aAuthor, const OSCL_String& aLangCode)
847 {
848     if (iInterfaceState != EPVMFNodeIdle &&
849             iInterfaceState != EPVMFNodeInitialized &&
850             iInterfaceState != EPVMFNodePrepared)
851         return PVMFErrInvalidState;
852 
853     iAuthor.iDataString = aAuthor;
854     iAuthor.iLangCode = ConvertLangCode(aLangCode);
855     return PVMFSuccess;
856 }
857 
858 ////////////////////////////////////////////////////////////////////////////
SetCopyright(const OSCL_wString & aCopyright,const OSCL_String & aLangCode)859 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCopyright(const OSCL_wString& aCopyright, const OSCL_String& aLangCode)
860 {
861     if (iInterfaceState != EPVMFNodeIdle &&
862             iInterfaceState != EPVMFNodeInitialized &&
863             iInterfaceState != EPVMFNodePrepared)
864         return PVMFErrInvalidState;
865 
866     iCopyright.iDataString = aCopyright;
867     iCopyright.iLangCode = ConvertLangCode(aLangCode);
868     return PVMFSuccess;
869 }
870 
871 ////////////////////////////////////////////////////////////////////////////
SetDescription(const OSCL_wString & aDescription,const OSCL_String & aLangCode)872 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetDescription(const OSCL_wString& aDescription, const OSCL_String& aLangCode)
873 {
874     if (iInterfaceState != EPVMFNodeIdle &&
875             iInterfaceState != EPVMFNodeInitialized &&
876             iInterfaceState != EPVMFNodePrepared)
877         return PVMFErrInvalidState;
878 
879     iDescription.iDataString = aDescription;
880     iDescription.iLangCode = ConvertLangCode(aLangCode);
881     return PVMFSuccess;
882 }
883 
884 ////////////////////////////////////////////////////////////////////////////
SetRating(const OSCL_wString & aRating,const OSCL_String & aLangCode)885 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetRating(const OSCL_wString& aRating, const OSCL_String& aLangCode)
886 {
887     if (iInterfaceState != EPVMFNodeIdle &&
888             iInterfaceState != EPVMFNodeInitialized &&
889             iInterfaceState != EPVMFNodePrepared)
890         return PVMFErrInvalidState;
891 
892     iRating.iDataString = aRating;
893     iRating.iLangCode = ConvertLangCode(aLangCode);
894     return PVMFSuccess;
895 }
896 
897 ////////////////////////////////////////////////////////////////////////////
SetCreationDate(const OSCL_wString & aCreationDate)898 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCreationDate(const OSCL_wString& aCreationDate)
899 {
900     if (iInterfaceState != EPVMFNodeIdle &&
901             iInterfaceState != EPVMFNodeInitialized &&
902             iInterfaceState != EPVMFNodePrepared)
903         return PVMFErrInvalidState;
904 
905     iCreationDate = aCreationDate;
906     return PVMFSuccess;
907 }
908 
909 ////////////////////////////////////////////////////////////////////////////
SetRealTimeAuthoring(const bool aRealTime)910 PVMFStatus PVMp4FFComposerNode::SetRealTimeAuthoring(const bool aRealTime)
911 {
912     if (iInterfaceState != EPVMFNodeIdle && iInterfaceState != EPVMFNodeInitialized)
913         return PVMFErrInvalidState;
914 
915     iRealTimeTS = aRealTime;
916     return PVMFSuccess;
917 }
918 
919 ////////////////////////////////////////////////////////////////////////////
SetAlbumInfo(const OSCL_wString & aAlbumTitle,const OSCL_String & aLangCode)920 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetAlbumInfo(const OSCL_wString& aAlbumTitle, const OSCL_String& aLangCode)
921 {
922     if (iInterfaceState != EPVMFNodeIdle &&
923             iInterfaceState != EPVMFNodeInitialized &&
924             iInterfaceState != EPVMFNodePrepared)
925         return PVMFErrInvalidState;
926 
927     iAlbumTitle.iDataString = aAlbumTitle;
928     iAlbumTitle.iLangCode = ConvertLangCode(aLangCode);
929     return PVMFSuccess;
930 }
931 
932 
933 ////////////////////////////////////////////////////////////////////////////
SetRecordingYear(uint16 aRecordingYear)934 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetRecordingYear(uint16 aRecordingYear)
935 {
936     if (iInterfaceState != EPVMFNodeIdle &&
937             iInterfaceState != EPVMFNodeInitialized &&
938             iInterfaceState != EPVMFNodePrepared)
939         return PVMFErrInvalidState;
940 
941     iRecordingYear = aRecordingYear;
942     return PVMFSuccess;
943 }
944 
945 ////////////////////////////////////////////////////////////////////////////
SetPerformer(const OSCL_wString & aPerformer,const OSCL_String & aLangCode)946 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetPerformer(const OSCL_wString& aPerformer, const OSCL_String& aLangCode)
947 {
948     if (iInterfaceState != EPVMFNodeIdle &&
949             iInterfaceState != EPVMFNodeInitialized &&
950             iInterfaceState != EPVMFNodePrepared)
951         return PVMFErrInvalidState;
952 
953     iPerformer.iDataString = aPerformer;
954     iPerformer.iLangCode = ConvertLangCode(aLangCode);
955     return PVMFSuccess;
956 }
957 
958 ////////////////////////////////////////////////////////////////////////////
SetGenre(const OSCL_wString & aGenre,const OSCL_String & aLangCode)959 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetGenre(const OSCL_wString& aGenre, const OSCL_String& aLangCode)
960 {
961     if (iInterfaceState != EPVMFNodeIdle &&
962             iInterfaceState != EPVMFNodeInitialized &&
963             iInterfaceState != EPVMFNodePrepared)
964         return PVMFErrInvalidState;
965 
966     iGenre.iDataString = aGenre;
967     iGenre.iLangCode = ConvertLangCode(aLangCode);
968     return PVMFSuccess;
969 }
970 ////////////////////////////////////////////////////////////////////////////
SetClassification(const OSCL_wString & aClassificationInfo,uint32 aClassificationEntity,uint16 aClassificationTable,const OSCL_String & aLangCode)971 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetClassification(const OSCL_wString& aClassificationInfo, uint32 aClassificationEntity, uint16 aClassificationTable, const OSCL_String& aLangCode)
972 {
973     if (iInterfaceState != EPVMFNodeIdle &&
974             iInterfaceState != EPVMFNodeInitialized &&
975             iInterfaceState != EPVMFNodePrepared)
976         return PVMFErrInvalidState;
977 
978     iClassification.iDataString = aClassificationInfo;
979     iClassification.iClassificationEntity = aClassificationEntity;
980     iClassification.iClassificationTable = aClassificationTable;
981     iClassification.iLangCode = ConvertLangCode(aLangCode);
982     return PVMFSuccess;
983 }
984 ////////////////////////////////////////////////////////////////////////////
SetKeyWord(const OSCL_wString & aKeyWordInfo,const OSCL_String & aLangCode)985 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetKeyWord(const OSCL_wString& aKeyWordInfo, const OSCL_String& aLangCode)
986 {
987     if (iInterfaceState != EPVMFNodeIdle &&
988             iInterfaceState != EPVMFNodeInitialized &&
989             iInterfaceState != EPVMFNodePrepared)
990         return PVMFErrInvalidState;
991 
992     PVMP4FFCN_KeyWord *KeyWord = NULL;
993 
994     uint16 langCode = ConvertLangCode(aLangCode);
995     KeyWord = OSCL_NEW(PVMP4FFCN_KeyWord, (aKeyWordInfo, aKeyWordInfo.get_size(), langCode));
996 
997     iKeyWordVector.push_back(KeyWord);
998 
999 
1000     return PVMFSuccess;
1001 }
1002 
1003 ////////////////////////////////////////////////////////////////////////////
SetLocationInfo(PvmfAssetInfo3GPPLocationStruct & aLocation_info)1004 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetLocationInfo(PvmfAssetInfo3GPPLocationStruct& aLocation_info)
1005 {
1006     if (iInterfaceState != EPVMFNodeIdle &&
1007             iInterfaceState != EPVMFNodeInitialized &&
1008             iInterfaceState != EPVMFNodePrepared)
1009         return PVMFErrInvalidState;
1010 
1011     iLocationInfo._location_name = NULL;
1012     uint32 size = oscl_strlen(aLocation_info._location_name);
1013     iLocationInfo._location_name = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10);
1014     oscl_strncpy(iLocationInfo._location_name, aLocation_info._location_name, size);
1015     iLocationInfo._location_name[size+1] = 0;
1016 
1017     iLocationInfo._astronomical_body = NULL;
1018     size = oscl_strlen(aLocation_info._astronomical_body);
1019     iLocationInfo._astronomical_body = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10);
1020     oscl_strncpy(iLocationInfo._astronomical_body, aLocation_info._astronomical_body, size);
1021     iLocationInfo._astronomical_body[size+1] = 0;
1022 
1023     iLocationInfo._additional_notes = NULL;
1024     size = oscl_strlen(aLocation_info._additional_notes);
1025     iLocationInfo._additional_notes = (oscl_wchar*)oscl_malloc(sizeof(oscl_wchar) * size + 10);
1026     oscl_strncpy(iLocationInfo._additional_notes, aLocation_info._additional_notes, size);
1027     iLocationInfo._additional_notes[size+1] = 0;
1028 
1029     iLocationInfo._role = aLocation_info._role;
1030     iLocationInfo._longitude = aLocation_info._longitude;
1031     iLocationInfo._latitude = aLocation_info._latitude;
1032     iLocationInfo._altitude = aLocation_info._altitude;
1033     iLocationInfo._langCode = ConvertLangCode(aLocation_info.Lang_code);
1034 
1035     return PVMFSuccess;
1036 }
1037 
1038 
1039 ////////////////////////////////////////////////////////////////////////////
1040 //                PVMp4FFCNTrackConfigInterface routines
1041 ////////////////////////////////////////////////////////////////////////////
SetTrackReference(const PVMFPortInterface & aPort,const PVMFPortInterface & aReferencePort)1042 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetTrackReference(const PVMFPortInterface& aPort,
1043         const PVMFPortInterface& aReferencePort)
1044 {
1045     if (iInterfaceState != EPVMFNodeInitialized)
1046         return PVMFErrInvalidState;
1047 
1048     int32 portIndex = -1;
1049     int32 refPortIndex = -1;
1050     PVMp4FFComposerPort* port = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, &aPort);
1051     PVMp4FFComposerPort* refPort = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, &aReferencePort);
1052 
1053     for (uint32 i = 0; i < iInPorts.size(); i++)
1054     {
1055         if (iInPorts[i] == port)
1056             portIndex = i;
1057         if (iInPorts[i] == refPort)
1058             refPortIndex = i;
1059     }
1060 
1061     if (portIndex > 0 && refPortIndex > 0)
1062     {
1063         iInPorts[portIndex]->SetReferencePort(iInPorts[refPortIndex]);
1064         return PVMFSuccess;
1065     }
1066     else
1067         return PVMFFailure;
1068 }
1069 
1070 ////////////////////////////////////////////////////////////////////////////
SetCodecSpecificInfo(const PVMFPortInterface & aPort,uint8 * aInfo,int32 aSize)1071 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetCodecSpecificInfo(const PVMFPortInterface& aPort,
1072         uint8* aInfo, int32 aSize)
1073 {
1074     PVMFStatus status = PVMFFailure;
1075 
1076     if ((status == PVMFSuccess) &&
1077             (iInterfaceState == EPVMFNodeStarted))
1078     {
1079         PVMp4FFComposerPort* port = OSCL_STATIC_CAST(PVMp4FFComposerPort*, &aPort);
1080         iMpeg4File->setDecoderSpecificInfo(aInfo, aSize, port->GetTrackId());
1081     }
1082 
1083     return status;
1084 }
1085 
1086 ////////////////////////////////////////////////////////////////////////////
1087 //          PvmfComposerSizeAndDurationInterface routines
1088 ////////////////////////////////////////////////////////////////////////////
SetMaxFileSize(bool aEnable,uint32 aMaxFileSizeBytes)1089 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetMaxFileSize(bool aEnable, uint32 aMaxFileSizeBytes)
1090 {
1091     iMaxFileSizeEnabled = aEnable;
1092     if (iMaxFileSizeEnabled)
1093     {
1094         iMaxFileSize = aMaxFileSizeBytes;
1095     }
1096     else
1097     {
1098         iMaxFileSize = 0;
1099     }
1100 
1101     return PVMFSuccess;
1102 }
1103 
1104 ////////////////////////////////////////////////////////////////////////////
GetMaxFileSizeConfig(bool & aEnable,uint32 & aMaxFileSizeBytes)1105 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetMaxFileSizeConfig(bool& aEnable, uint32& aMaxFileSizeBytes)
1106 {
1107     aEnable = iMaxFileSizeEnabled;
1108     aMaxFileSizeBytes = iMaxFileSize;
1109 }
1110 
1111 ////////////////////////////////////////////////////////////////////////////
SetMaxDuration(bool aEnable,uint32 aMaxDurationMilliseconds)1112 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetMaxDuration(bool aEnable, uint32 aMaxDurationMilliseconds)
1113 {
1114     iMaxDurationEnabled = aEnable;
1115     if (iMaxDurationEnabled)
1116     {
1117         iMaxTimeDuration = aMaxDurationMilliseconds;
1118     }
1119     else
1120     {
1121         iMaxTimeDuration = 0;
1122     }
1123 
1124     return PVMFSuccess;
1125 }
1126 
1127 ////////////////////////////////////////////////////////////////////////////
GetMaxDurationConfig(bool & aEnable,uint32 & aMaxDurationMilliseconds)1128 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetMaxDurationConfig(bool& aEnable, uint32& aMaxDurationMilliseconds)
1129 {
1130     aEnable = iMaxDurationEnabled;
1131     aMaxDurationMilliseconds = iMaxTimeDuration;
1132 }
1133 
1134 ////////////////////////////////////////////////////////////////////////////
SetFileSizeProgressReport(bool aEnable,uint32 aReportFrequency)1135 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetFileSizeProgressReport(bool aEnable, uint32 aReportFrequency)
1136 {
1137     iFileSizeReportEnabled = aEnable;
1138     if (iFileSizeReportEnabled)
1139     {
1140         iFileSizeReportFreq = aReportFrequency;
1141     }
1142 
1143     return PVMFSuccess;
1144 }
1145 
1146 ////////////////////////////////////////////////////////////////////////////
GetFileSizeProgressReportConfig(bool & aEnable,uint32 & aReportFrequency)1147 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetFileSizeProgressReportConfig(bool& aEnable, uint32& aReportFrequency)
1148 {
1149     aEnable = iFileSizeReportEnabled;
1150     aReportFrequency = iFileSizeReportFreq;
1151 }
1152 
1153 ////////////////////////////////////////////////////////////////////////////
SetDurationProgressReport(bool aEnable,uint32 aReportFrequency)1154 OSCL_EXPORT_REF PVMFStatus PVMp4FFComposerNode::SetDurationProgressReport(bool aEnable, uint32 aReportFrequency)
1155 {
1156     iDurationReportEnabled = aEnable;
1157     if (iDurationReportEnabled)
1158     {
1159         iDurationReportFreq = aReportFrequency;
1160     }
1161 
1162     return PVMFSuccess;
1163 }
1164 
1165 ////////////////////////////////////////////////////////////////////////////
GetDurationProgressReportConfig(bool & aEnable,uint32 & aReportFrequency)1166 OSCL_EXPORT_REF void PVMp4FFComposerNode::GetDurationProgressReportConfig(bool& aEnable, uint32& aReportFrequency)
1167 {
1168     aEnable = iDurationReportEnabled;
1169     aReportFrequency = iDurationReportFreq;
1170 }
1171 
1172 ////////////////////////////////////////////////////////////////////////////
1173 //            PVMFPortActivityHandler routines
1174 ////////////////////////////////////////////////////////////////////////////
HandlePortActivity(const PVMFPortActivity & aActivity)1175 void PVMp4FFComposerNode::HandlePortActivity(const PVMFPortActivity& aActivity)
1176 {
1177     OSCL_UNUSED_ARG(aActivity);
1178     // Scheduling to process port activities are handled in the port itself
1179 }
1180 
1181 ////////////////////////////////////////////////////////////////////////////
1182 //                    OsclActiveObject routines
1183 ////////////////////////////////////////////////////////////////////////////
Run()1184 void PVMp4FFComposerNode::Run()
1185 {
1186     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::Run: iInterfaceState=%d", iInterfaceState));
1187 
1188     if (!iCmdQueue.empty())
1189     {
1190         if (ProcessCommand(iCmdQueue.front()))
1191         {
1192             //note: need to check the state before re-scheduling
1193             //since the node could have been reset in the ProcessCommand
1194             //call.
1195             if (iInterfaceState != EPVMFNodeCreated)
1196                 RunIfNotReady();
1197             return;
1198         }
1199     }
1200 
1201     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::Run: Out. iInterfaceState=%d", iInterfaceState));
1202 }
1203 
1204 
1205 ////////////////////////////////////////////////////////////////////////////
1206 //                   Command Processing routines
1207 ////////////////////////////////////////////////////////////////////////////
QueueCommandL(PVMp4FFCNCmd & aCmd)1208 PVMFCommandId PVMp4FFComposerNode::QueueCommandL(PVMp4FFCNCmd& aCmd)
1209 {
1210     int32 err = 0;
1211     PVMFCommandId id = 0;
1212 
1213     OSCL_TRY(err, id = iCmdQueue.AddL(aCmd););
1214     OSCL_FIRST_CATCH_ANY(err,
1215                          OSCL_LEAVE(err);
1216                          return 0;
1217                         );
1218 
1219     // Wakeup the AO
1220     RunIfNotReady();
1221     return id;
1222 }
1223 
1224 ////////////////////////////////////////////////////////////////////////////
ProcessCommand(PVMp4FFCNCmd & aCmd)1225 bool PVMp4FFComposerNode::ProcessCommand(PVMp4FFCNCmd& aCmd)
1226 {
1227     //normally this node will not start processing one command
1228     //until the prior one is finished.  However, a hi priority
1229     //command such as Cancel must be able to interrupt a command
1230     //in progress.
1231     if (!iCurrentCmd.empty() && !aCmd.hipri())
1232         return false;
1233 
1234     switch (aCmd.iCmd)
1235     {
1236         case PVMF_GENERIC_NODE_QUERYUUID:
1237             DoQueryUuid(aCmd);
1238             break;
1239 
1240         case PVMF_GENERIC_NODE_QUERYINTERFACE:
1241             DoQueryInterface(aCmd);
1242             break;
1243 
1244         case PVMF_GENERIC_NODE_REQUESTPORT:
1245             DoRequestPort(aCmd);
1246             break;
1247 
1248         case PVMF_GENERIC_NODE_RELEASEPORT:
1249             DoReleasePort(aCmd);
1250             break;
1251 
1252         case PVMF_GENERIC_NODE_INIT:
1253             DoInit(aCmd);
1254             break;
1255 
1256         case PVMF_GENERIC_NODE_PREPARE:
1257             DoPrepare(aCmd);
1258             break;
1259 
1260         case PVMF_GENERIC_NODE_START:
1261             DoStart(aCmd);
1262             break;
1263 
1264         case PVMF_GENERIC_NODE_STOP:
1265             DoStop(aCmd);
1266             break;
1267 
1268         case PVMF_GENERIC_NODE_FLUSH:
1269             DoFlush(aCmd);
1270             break;
1271 
1272         case PVMF_GENERIC_NODE_PAUSE:
1273             DoPause(aCmd);
1274             break;
1275 
1276         case PVMF_GENERIC_NODE_RESET:
1277             DoReset(aCmd);
1278             break;
1279 
1280         case PVMF_GENERIC_NODE_CANCELALLCOMMANDS:
1281             DoCancelAllCommands(aCmd);
1282             break;
1283 
1284         case PVMF_GENERIC_NODE_CANCELCOMMAND:
1285             DoCancelCommand(aCmd);
1286             break;
1287 
1288         default://unknown command type
1289             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1290             break;
1291     }
1292 
1293     return true;
1294 }
1295 
1296 ////////////////////////////////////////////////////////////////////////////
CommandComplete(PVMp4FFCNCmdQueue & aCmdQueue,PVMp4FFCNCmd & aCmd,PVMFStatus aStatus,OsclAny * aEventData)1297 void PVMp4FFComposerNode::CommandComplete(PVMp4FFCNCmdQueue& aCmdQueue, PVMp4FFCNCmd& aCmd,
1298         PVMFStatus aStatus, OsclAny* aEventData)
1299 {
1300     LOG_STACK_TRACE((0, "PVMp4FFComposerNode:CommandComplete: Id %d Cmd %d Status %d Context %d Data %d"
1301                      , aCmd.iId, aCmd.iCmd, aStatus, aCmd.iContext, aEventData));
1302 
1303     //create response
1304     PVMFCmdResp resp(aCmd.iId, aCmd.iContext, aStatus, aEventData);
1305     PVMFSessionId session = aCmd.iSession;
1306 
1307     //Erase the command from the queue.
1308     aCmdQueue.Erase(&aCmd);
1309 
1310     //Report completion to the session observer.
1311     ReportCmdCompleteEvent(session, resp);
1312 }
1313 
1314 //////////////////////////////////////////////////////////////////////////////////
DoQueryUuid(PVMp4FFCNCmd & aCmd)1315 void PVMp4FFComposerNode::DoQueryUuid(PVMp4FFCNCmd& aCmd)
1316 {
1317     OSCL_String* mimetype;
1318     Oscl_Vector<PVUuid, OsclMemAllocator> *uuidvec;
1319     bool exactmatch;
1320     aCmd.Parse(mimetype, uuidvec, exactmatch);
1321 
1322     uuidvec->push_back(KPVMp4FFCNClipConfigUuid);
1323     uuidvec->push_back(KPVMp4FFCNTrackConfigUuid);
1324     uuidvec->push_back(PvmfComposerSizeAndDurationUuid);
1325 
1326     CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1327 }
1328 
1329 //////////////////////////////////////////////////////////////////////////////////
DoQueryInterface(PVMp4FFCNCmd & aCmd)1330 void PVMp4FFComposerNode::DoQueryInterface(PVMp4FFCNCmd& aCmd)
1331 {
1332     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1333                     (0, "PVMp4FFComposerNode::DoQueryInterface"));
1334 
1335     PVUuid* uuid;
1336     PVInterface** ptr;
1337     aCmd.Parse(uuid, ptr);
1338 
1339     if (queryInterface(*uuid, *ptr))
1340     {
1341         CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1342     }
1343     else
1344     {
1345         CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1346     }
1347 }
1348 
1349 
1350 //////////////////////////////////////////////////////////////////////////////////
DoRequestPort(PVMp4FFCNCmd & aCmd)1351 void PVMp4FFComposerNode::DoRequestPort(PVMp4FFCNCmd& aCmd)
1352 {
1353     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1354                     (0, "PVMp4FFComposerNode::DoRequestPort() In"));
1355 
1356     int32 tag;
1357     OSCL_String* portconfig;
1358     aCmd.Parse(tag, portconfig);
1359 
1360     //validate the tag...
1361     switch (tag)
1362     {
1363         case PVMF_MP4FFCN_PORT_TYPE_SINK:
1364             if (iInPorts.size() >= PVMF_MP4FFCN_MAX_INPUT_PORT)
1365             {
1366                 LOG_ERR((0, "PVMp4FFComposerNode::DoRequestPort: Error - Max number of input port already allocated"));
1367                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1368                 return;
1369             }
1370             break;
1371 
1372         default:
1373             //bad port tag
1374             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1375                             (0, "PVMp4FFComposerNode::DoRequestPort: Error - Invalid port tag"));
1376             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1377             return;
1378     }
1379 
1380     //Allocate a new port
1381     OsclAny *ptr = NULL;
1382     int32 err;
1383     OSCL_TRY(err,
1384              ptr = iInPorts.Allocate();
1385              if (!ptr)
1386              OSCL_LEAVE(OsclErrNoMemory);
1387             );
1388 
1389     OSCL_FIRST_CATCH_ANY(err,
1390                          PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1391                                          (0, "PVMp4FFComposerNode::DoRequestPort: Error - iInPorts Out of memory"));
1392                          CommandComplete(iCmdQueue, aCmd, PVMFErrNoMemory);
1393                          return;
1394                         );
1395 
1396     OSCL_StackString<20> portname;
1397     portname = "PVMP4ComposerIn";
1398 
1399     PVMp4FFComposerPort* port = OSCL_PLACEMENT_NEW(ptr, PVMp4FFComposerPort(tag, this, Priority(), portname.get_cstr()));
1400 
1401     // if format was provided in mimestring, set it now.
1402     if (portconfig)
1403     {
1404         PVMFFormatType format = portconfig->get_str();
1405         if (format == PVMF_MIME_3GPP_TIMEDTEXT ||
1406                 format == PVMF_MIME_H264_VIDEO_MP4 ||
1407                 format == PVMF_MIME_M4V ||
1408                 format == PVMF_MIME_H2631998 ||
1409                 format == PVMF_MIME_H2632000 ||
1410                 format == PVMF_MIME_AMR_IETF ||
1411                 format == PVMF_MIME_AMRWB_IETF ||
1412                 format == PVMF_MIME_ADIF ||
1413                 format == PVMF_MIME_ADTS ||
1414                 format == PVMF_MIME_MPEG4_AUDIO)
1415         {
1416             port->SetFormat(format);
1417         }
1418         else
1419         {
1420             CommandComplete(iCmdQueue, aCmd, PVMFErrNotSupported);
1421             return;
1422         }
1423     }
1424 
1425     //Add the port to the port vector.
1426     OSCL_TRY(err, iInPorts.AddL(port););
1427     OSCL_FIRST_CATCH_ANY(err,
1428                          iInPorts.DestructAndDealloc(port);
1429                          CommandComplete(iCmdQueue, aCmd, PVMFErrNoMemory);
1430                          return;
1431                         );
1432 
1433     // Return the port pointer to the caller.
1434     CommandComplete(iCmdQueue, aCmd, PVMFSuccess, (OsclAny*)port);
1435 }
1436 
1437 //////////////////////////////////////////////////////////////////////////////////
DoReleasePort(PVMp4FFCNCmd & aCmd)1438 void PVMp4FFComposerNode::DoReleasePort(PVMp4FFCNCmd& aCmd)
1439 {
1440     //Find the port in the port vector
1441     PVMFPortInterface* p = NULL;
1442 
1443     for (uint32 i = 0; i < iInPorts.size(); i++)
1444     {
1445         aCmd.Parse(p);
1446 
1447         PVMp4FFComposerPort* port = (PVMp4FFComposerPort*)p;
1448 
1449         PVMp4FFComposerPort** portPtr = iInPorts.FindByValue(port);
1450         if (portPtr)
1451         {
1452             //delete the port.
1453             iInPorts.Erase(portPtr);
1454 
1455 #ifdef _TEST_AE_ERROR_HANDLING
1456             if (FAIL_NODE_CMD_RELEASE_PORT == iErrorNodeCmd)
1457             {
1458                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1459 
1460             }
1461             else
1462             {
1463                 CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1464             }
1465 #else
1466             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1467 #endif
1468 
1469         }
1470         else
1471         {
1472             //port not found.
1473             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1474         }
1475 
1476     }
1477 }
1478 
1479 //////////////////////////////////////////////////////////////////////////////////
DoInit(PVMp4FFCNCmd & aCmd)1480 void PVMp4FFComposerNode::DoInit(PVMp4FFCNCmd& aCmd)
1481 {
1482     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMp4FFComposerNode::DoInitNode() In"));
1483 
1484     switch (iInterfaceState)
1485     {
1486         case EPVMFNodeIdle:
1487             // Creation of file format library is done in DoStart. Nothing to do here.
1488             SetState(EPVMFNodeInitialized);
1489             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1490             break;
1491         case EPVMFNodeInitialized:
1492             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1493             break;
1494 
1495         default:
1496             CommandComplete(iCmdQueue, aCmd, PVMFErrInvalidState);
1497             break;
1498     }
1499 }
1500 
1501 //////////////////////////////////////////////////////////////////////////////////
DoPrepare(PVMp4FFCNCmd & aCmd)1502 void PVMp4FFComposerNode::DoPrepare(PVMp4FFCNCmd& aCmd)
1503 {
1504     switch (iInterfaceState)
1505     {
1506         case EPVMFNodeInitialized:
1507             // Creation of file format library is done in DoStart. Nothing to do here.
1508             SetState(EPVMFNodePrepared);
1509             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1510             break;
1511         case EPVMFNodePrepared:
1512             CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
1513             break;
1514 
1515         default:
1516             CommandComplete(iCmdQueue, aCmd, PVMFErrInvalidState);
1517             break;
1518     }
1519 }
1520 
1521 //////////////////////////////////////////////////////////////////////////////////
DoStart(PVMp4FFCNCmd & aCmd)1522 void PVMp4FFComposerNode::DoStart(PVMp4FFCNCmd& aCmd)
1523 {
1524     PVMFStatus status = PVMFSuccess;
1525     uint32 i = 0;
1526 #ifdef _TEST_AE_ERROR_HANDLING
1527     if (FAIL_NODE_CMD_START == iErrorNodeCmd)
1528     {
1529         iInterfaceState = EPVMFNodeError;
1530     }
1531 #endif
1532     switch (iInterfaceState)
1533     {
1534         case EPVMFNodePrepared:
1535         {
1536             iPostfix = _STRLIT("00");
1537             iOutputPath = _STRLIT("");
1538             int32 pos = 0;
1539             for (pos = iFileName.get_size() - 1; pos >= 0; pos--)
1540             {
1541                 if (iFileName[pos] == SLASH)
1542                     break;
1543             }
1544 
1545             if (pos == -1)
1546             {
1547                 iOutputPath = _STRLIT(".");
1548             }
1549             else
1550             {
1551                 for (i = 0; i <= (uint32) pos; i++)
1552                     iOutputPath += iFileName[i];
1553             }
1554 
1555 
1556 
1557             iFileType = 0;
1558             for (i = 0; i < iInPorts.size(); i++)
1559             {
1560                 if (iInPorts[i]->GetFormat() == PVMF_MIME_H264_VIDEO_MP4 ||
1561                         iInPorts[i]->GetFormat() == PVMF_MIME_M4V ||
1562                         iInPorts[i]->GetFormat() == PVMF_MIME_H2631998 ||
1563                         iInPorts[i]->GetFormat() == PVMF_MIME_H2632000)
1564                 {
1565                     iFileType |= FILE_TYPE_VIDEO;
1566                 }
1567                 else if (iInPorts[i]->GetFormat() == PVMF_MIME_AMR_IETF ||
1568                          iInPorts[i]->GetFormat() == PVMF_MIME_AMRWB_IETF ||
1569                          iInPorts[i]->GetFormat() == PVMF_MIME_MPEG4_AUDIO)
1570                 {
1571                     iFileType |= FILE_TYPE_AUDIO;
1572                 }
1573                 else if (iInPorts[i]->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT)
1574                 {
1575                     iFileType |= FILE_TYPE_TIMED_TEXT;
1576                 }
1577                 else
1578                 {
1579                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1580                                     (0, "PVMp4FFComposerNode::DoStart: Error - Unsupported format"));
1581                     return;
1582                 }
1583             }
1584 
1585             if (iMpeg4File)
1586             {
1587                 LOG_ERR((0, "PVMp4FFComposerNode::DoStart: Error - File format library already exists"));
1588                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1589                 return;
1590             }
1591 
1592             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1593                             (0, "PVMp4FFComposerNode::DoStart: Calling PVA_FF_IMpeg4File::createMP4File(%d,0x%x,%d)",
1594                              iFileType, &iFs, iAuthoringMode));
1595 #ifdef _TEST_AE_ERROR_HANDLING //test case to fail mp4 file parser
1596             if (iErrorCreateComposer)
1597             {
1598                 //to fail createMP4File()
1599                 OSCL_wHeapString<OsclMemAllocator> ErrFileName;
1600 
1601                 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
1602                              (void*) & iFs, iAuthoringMode, ErrFileName, iCacheSize);
1603 
1604             }
1605             else
1606             {
1607                 if (iFileObject != NULL)
1608                 {
1609                     iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iFileObject, iCacheSize);
1610 
1611                 }
1612                 else
1613                 {
1614 
1615                     iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
1616                                  (void*) & iFs, iAuthoringMode, iFileName, iCacheSize);
1617 
1618                 }
1619             }
1620 #else
1621             if (iFileObject != NULL)
1622             {
1623                 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iAuthoringMode, iFileObject, iCacheSize);
1624 
1625             }
1626             else
1627             {
1628                 iMpeg4File = PVA_FF_IMpeg4File::createMP4File(iFileType, iOutputPath, iPostfix,
1629                              (void*) & iFs, iAuthoringMode, iFileName, iCacheSize);
1630             }
1631 #endif
1632             if (!iMpeg4File)
1633             {
1634                 PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1635                                 (0, "PVMp4FFComposerNode::DoStart: Error - PVA_FF_IMpeg4File::createMP4File failed"));
1636                 CommandComplete(iCmdQueue, aCmd, PVMFFailure);
1637                 return;
1638             }
1639 
1640             iMpeg4File->setPresentationTimescale(iPresentationTimescale);
1641             iMpeg4File->setVersion(iVersion.iDataString, iVersion.iLangCode);
1642             iMpeg4File->setTitle(iTitle.iDataString, iTitle.iLangCode);
1643             iMpeg4File->setAuthor(iAuthor.iDataString, iAuthor.iLangCode);
1644             iMpeg4File->setCopyright(iCopyright.iDataString, iCopyright.iLangCode);
1645             iMpeg4File->setDescription(iDescription.iDataString, iDescription.iLangCode);
1646             iMpeg4File->setRating(iRating.iDataString, iRating.iLangCode);
1647             if(iCreationDate.get_size() > 0)
1648             {
1649                 iMpeg4File->setCreationDate(iCreationDate);
1650             }
1651             iMpeg4File->setMovieFragmentDuration(iMovieFragmentDuration);
1652             iMpeg4File->setAlbumInfo(iAlbumTitle.iDataString, iAlbumTitle.iLangCode);
1653             iMpeg4File->setRecordingYear(iRecordingYear);
1654 
1655             iMpeg4File->setPerformer(iPerformer.iDataString, iPerformer.iLangCode);
1656             iMpeg4File->setGenre(iGenre.iDataString, iGenre.iLangCode);
1657             iMpeg4File->setClassification(iClassification.iDataString, iClassification.iClassificationEntity, iClassification.iClassificationTable, iClassification.iLangCode);
1658 
1659             for (i = 0; i < iKeyWordVector.size() ; i++)
1660             {
1661                 iMpeg4File->setKeyWord(iKeyWordVector[i]->iKeyWordSize, iKeyWordVector[i]->iData_String, iKeyWordVector[i]->iLang_Code);
1662             }
1663 
1664             iMpeg4File->setLocationInfo(&iLocationInfo);
1665             for (i = 0; i < iInPorts.size(); i++)
1666             {
1667                 status = AddTrack(iInPorts[i]);
1668                 if (status != PVMFSuccess)
1669                 {
1670                     CommandComplete(iCmdQueue, aCmd, status);
1671                     return;
1672                 }
1673             }
1674 
1675             // Check for and set reference tracks after track IDs are assigned
1676             PVMp4FFComposerPort* refPort = NULL;
1677             for (i = 0; i < iInPorts.size(); i++)
1678             {
1679                 refPort = OSCL_STATIC_CAST(PVMp4FFComposerPort*, iInPorts[i]->GetReferencePort());
1680                 if (refPort)
1681                 {
1682                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1683                                     (0, "PVMp4FFComposerNode::DoStart: Calling addTrackReference(%d, %d)",
1684                                      iInPorts[i]->GetTrackId(), refPort->GetTrackId()));
1685                     iMpeg4File->addTrackReference(iInPorts[i]->GetTrackId(), refPort->GetTrackId());
1686                 }
1687             }
1688 
1689             iMpeg4File->prepareToEncode();
1690 
1691             iInitTSOffset = true;
1692             iTSOffset = 0;
1693             SetState(EPVMFNodeStarted);
1694             break;
1695         }
1696 
1697         case EPVMFNodePaused:
1698             SetState(EPVMFNodeStarted);
1699             for (i = 0; i < iInPorts.size(); i++)
1700                 ((PVMp4FFComposerPort*)iInPorts[i])->ProcessIncomingMsgReady();
1701             break;
1702         case EPVMFNodeStarted:
1703             status = PVMFSuccess;
1704             break;
1705         default:
1706             status = PVMFErrInvalidState;
1707             break;
1708     }
1709 
1710     CommandComplete(iCmdQueue, aCmd, status);
1711 }
1712 
1713 //////////////////////////////////////////////////////////////////////////////////
AddTrack(PVMp4FFComposerPort * aPort)1714 PVMFStatus PVMp4FFComposerNode::AddTrack(PVMp4FFComposerPort *aPort)
1715 {
1716     int32 codecType = 0;
1717     int32 mediaType = 0;
1718     int32 trackId = 0;
1719     PVMP4FFCNFormatSpecificConfig* config = aPort->GetFormatSpecificConfig();
1720     if (!config)
1721     {
1722         LOG_ERR((0, "PVMp4FFComposerNode::AddTrack: Error - GetFormatSpecificConfig failed"));
1723         return PVMFFailure;
1724     }
1725 
1726     if (aPort->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT)
1727     {
1728         codecType = CODEC_TYPE_TIMED_TEXT;
1729         mediaType = MEDIA_TYPE_TEXT;
1730     }
1731     else if (aPort->GetFormat() == PVMF_MIME_H264_VIDEO_MP4)
1732     {
1733         codecType = CODEC_TYPE_AVC_VIDEO;
1734         mediaType = MEDIA_TYPE_VISUAL;
1735     }
1736     else if (aPort->GetFormat() == PVMF_MIME_M4V)
1737     {
1738         codecType = CODEC_TYPE_MPEG4_VIDEO;
1739         mediaType = MEDIA_TYPE_VISUAL;
1740     }
1741     else if (aPort->GetFormat() == PVMF_MIME_H2631998 ||
1742              aPort->GetFormat() == PVMF_MIME_H2632000)
1743     {
1744         codecType = CODEC_TYPE_BASELINE_H263_VIDEO;
1745         mediaType = MEDIA_TYPE_VISUAL;
1746     }
1747     else if (aPort->GetFormat() == PVMF_MIME_AMR_IETF)
1748     {
1749         codecType = CODEC_TYPE_AMR_AUDIO;
1750         mediaType = MEDIA_TYPE_AUDIO;
1751     }
1752     else if (aPort->GetFormat() == PVMF_MIME_AMRWB_IETF)
1753     {
1754         codecType = CODEC_TYPE_AMR_WB_AUDIO;
1755         mediaType = MEDIA_TYPE_AUDIO;
1756     }
1757     else if (aPort->GetFormat() ==  PVMF_MIME_MPEG4_AUDIO)
1758     {
1759         codecType = CODEC_TYPE_AAC_AUDIO;
1760         mediaType = MEDIA_TYPE_AUDIO;
1761     }
1762     else
1763     {
1764         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1765                         (0, "PVMp4FFComposerNode::AddTrack: Error - Unsupported format"));
1766         return PVMFFailure;
1767     }
1768 
1769     aPort->SetCodecType(codecType);
1770 
1771     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1772                     (0, "PVMp4FFComposerNode::AddTrack: Calling PVA_FF_IMpeg4File::addTrack(0x%x,0x%x)",
1773                      mediaType, codecType));
1774 #ifdef _TEST_AE_ERROR_HANDLING
1775     if (aPort->GetFormat() == iErrorAddTrack)
1776     {
1777         return PVMFFailure;
1778     }
1779 #endif
1780     trackId = iMpeg4File->addTrack(mediaType, codecType);
1781 #ifdef _TEST_AE_ERROR_HANDLING
1782     if (iErrorHandlingAddTrack)
1783     {
1784         trackId = 0;
1785     }
1786 #endif
1787     if (trackId == 0)
1788     {
1789         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
1790                         (0, "PVMp4FFComposerNode::AddTrack: Error - PVA_FF_IMpeg4File::addTrack failed"));
1791         return PVMFFailure;
1792     }
1793     aPort->SetTrackId(trackId);
1794     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1795                     (0, "PVMp4FFComposerNode::AddTrack: PVA_FF_IMpeg4File::addTrack success. trackID=%d", trackId));
1796 #if PROFILING_ON
1797 
1798     for (uint32 k = 0; k < 3; k++)
1799     {
1800         if (iStats[k].iTrackId == 0)
1801         {
1802             iStats[k].iTrackId = trackId;
1803             break;
1804         }
1805     }
1806 #endif
1807 
1808     switch (mediaType)
1809     {
1810         case MEDIA_TYPE_AUDIO:
1811         {
1812             iMpeg4File->setTargetBitrate(trackId, config->iBitrate);
1813             iMpeg4File->setTimeScale(trackId, config->iTimescale);
1814             PVMP4FFComposerAudioEncodeParams audioParams;
1815             audioParams.numberOfChannels = config->iNumberOfChannels;
1816             audioParams.samplingRate = config->iSamplingRate;
1817             audioParams.bitsPerSample = config->iBitsPerSample;
1818             iMpeg4File->setAudioEncodeParams(trackId, audioParams);
1819             break;
1820         }
1821 
1822         case MEDIA_TYPE_VISUAL:
1823             switch (codecType)
1824             {
1825                 case CODEC_TYPE_BASELINE_H263_VIDEO:
1826                     iMpeg4File->setH263ProfileLevel(trackId, config->iH263Profile, config->iH263Level);
1827                     // Don't break here. Continue to set other video properties
1828                 case CODEC_TYPE_AVC_VIDEO:
1829                 case CODEC_TYPE_MPEG4_VIDEO:
1830                     iMpeg4File->setTargetBitrate(trackId, config->iBitrate, config->iBitrate, 0);
1831                     iMpeg4File->setTimeScale(trackId, config->iTimescale);
1832                     iMpeg4File->setVideoParams(trackId, (float)config->iFrameRate,
1833                                                (uint16)config->iIFrameInterval, config->iWidth, config->iHeight);
1834                     break;
1835             }
1836             break;
1837         case MEDIA_TYPE_TEXT:
1838             iMpeg4File->setTargetBitrate(trackId, config->iBitrate);
1839             iMpeg4File->setTimeScale(trackId, config->iTimescale);
1840             break;
1841 
1842     }
1843 
1844     return PVMFSuccess;
1845 }
1846 
1847 //////////////////////////////////////////////////////////////////////////////////
DoStop(PVMp4FFCNCmd & aCmd)1848 void PVMp4FFComposerNode::DoStop(PVMp4FFCNCmd& aCmd)
1849 {
1850     PVMFStatus status = PVMFSuccess;
1851 #if PROFILING_ON
1852     if (!oDiagnosticsLogged)
1853     {
1854         LogDiagnostics();
1855     }
1856 #endif
1857 #ifdef _TEST_AE_ERROR_HANDLING
1858     if (FAIL_NODE_CMD_STOP == iErrorNodeCmd)
1859     {
1860         iInterfaceState = EPVMFNodeError;
1861     }
1862 #endif
1863     switch (iInterfaceState)
1864     {
1865         case EPVMFNodeStarted:
1866         case EPVMFNodePaused:
1867         {
1868 #ifdef ANDROID
1869             iFragmentWriter->flush();
1870 #endif
1871             if (!iNodeEndOfDataReached)
1872             {
1873                 WriteDecoderSpecificInfo();
1874                 if (iSampleInTrack)
1875                 {
1876                     status = RenderToFile();
1877                 }
1878 
1879                 iSampleInTrack = false;
1880             }
1881 
1882             iNodeEndOfDataReached = false;
1883             for (uint32 ii = 0; ii < iInPorts.size(); ii++)
1884             {
1885                 iInPorts[ii]->iEndOfDataReached = false;
1886             }
1887         }
1888         SetState(EPVMFNodePrepared);
1889         break;
1890         case EPVMFNodePrepared:
1891             status = PVMFSuccess;
1892             break;
1893         default:
1894             status = PVMFErrInvalidState;
1895             break;
1896     }
1897 
1898     CommandComplete(iCmdQueue, aCmd, status);
1899 }
1900 
1901 //////////////////////////////////////////////////////////////////////////////////
WriteDecoderSpecificInfo()1902 void PVMp4FFComposerNode::WriteDecoderSpecificInfo()
1903 {
1904     uint32 i;
1905     uint32 offset = 0;
1906     iConfigSize = 0;
1907     int32 trackId;
1908 
1909     if (iformat_h264 == PVMF_MIME_H264_VIDEO_MP4)
1910     {
1911         trackId = iTrackId_H264;
1912 
1913         for (i = 0; i < memvector_sps.size(); i++)
1914         {
1915             iConfigSize += 2;//2 bytes for SPS_len
1916             iConfigSize += memvector_sps[i]->len;
1917         }
1918 
1919         for (i = 0; i < memvector_pps.size(); i++)
1920         {
1921             iConfigSize += 2;//2 bytes for PPS_len
1922             iConfigSize += memvector_pps[i]->len;
1923         }
1924         iConfigSize = iConfigSize + 2;//extra two bytes for nunSPS and NumPPS
1925         pConfig = (uint8*)(OSCL_MALLOC(sizeof(uint8) * iConfigSize));
1926 
1927 
1928         //currently we are ignoring NAL Length information
1929         oscl_memcpy((void*)(pConfig + offset), (const void*)&iNum_SPS_Set, 1);//Writing Number of SPS sets
1930         offset += 1;
1931 
1932         for (i = 0; i < memvector_sps.size(); i++)
1933         {
1934             oscl_memcpy((void*)(pConfig + offset), (const void*)&memvector_sps[i]->len, 2);//Writing length of SPS
1935             offset += 2;
1936             oscl_memcpy((void*)(pConfig + offset), memvector_sps[i]->ptr, memvector_sps[i]->len);
1937             offset = offset + memvector_sps[i]->len;
1938         }
1939 
1940         oscl_memcpy((void*)(pConfig + offset), (const void*)&iNum_PPS_Set, 1);//Writing Number of PPS sets
1941         offset += 1;
1942 
1943         for (i = 0; i < memvector_pps.size(); i++)
1944         {
1945             oscl_memcpy((void*)(pConfig + offset), (const void*)&memvector_pps[i]->len, 2);//Writing length of PPS
1946             offset += 2;//2 bytes for PPS Length
1947             oscl_memcpy((void*)(pConfig + offset), memvector_pps[i]->ptr, memvector_pps[i]->len);
1948             offset = offset + memvector_pps[i]->len;
1949         }
1950         iMpeg4File->setDecoderSpecificInfo(pConfig, iConfigSize, trackId);
1951     }
1952 
1953     if (iformat_text == PVMF_MIME_3GPP_TIMEDTEXT)
1954     {
1955         for (uint32 ii = 0; ii < textdecodervector.size(); ii++)
1956         {
1957             trackId = iTrackId_Text;
1958             iMpeg4File->setTextDecoderSpecificInfo(textdecodervector[ii], trackId);
1959         }
1960     }
1961 
1962 }
1963 //////////////////////////////////////////////////////////////////////////////////
RenderToFile()1964 PVMFStatus PVMp4FFComposerNode::RenderToFile()
1965 {
1966     PVMFStatus status = PVMFSuccess;
1967 
1968     // Clear queued messages in ports
1969     uint32 i;
1970     for (i = 0; i < iInPorts.size(); i++)
1971         iInPorts[i]->ClearMsgQueues();
1972 #ifdef _TEST_AE_ERROR_HANDLING //to fail renderToFile
1973     if (iErrorRenderToFile)
1974     {
1975         if (iMpeg4File)
1976         {
1977             PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
1978             iMpeg4File = NULL;
1979         }
1980     }
1981 #endif
1982 
1983 #ifdef ANDROID
1984     iFragmentWriter->flush();
1985 #endif
1986 
1987     if (!iMpeg4File || !iMpeg4File->renderToFile(iFileName))
1988     {
1989         LOG_ERR((0, "PVMp4FFComposerNode::RenderToFile: Error - renderToFile failed"));
1990         ReportErrorEvent(PVMF_MP4FFCN_ERROR_FINALIZE_OUTPUT_FILE_FAILED);
1991         status = PVMFFailure;
1992     }
1993     else
1994     {
1995 #if PROFILING_ON
1996         // Statistics
1997 
1998         for (i = 0; i < 3; i++)
1999         {
2000             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2001                             (0, "PVMp4FFComposerNode Stats: TrackId=%d, NumFrame=%d, Duration=%d",
2002                              iStats[i].iTrackId, iStats[i].iNumFrames, iStats[i].iDuration));
2003             oscl_memset(&(iStats[i]), 0, sizeof(PVMp4FFCNStats));
2004         }
2005 #endif
2006 
2007         LOGDATATRAFFIC((0, "PVMp4FFComposerNode::RenderToFile() Done"));
2008         // Delete file format library
2009         if (iMpeg4File)
2010         {
2011             PVA_FF_IMpeg4File::DestroyMP4FileObject(iMpeg4File);
2012             iMpeg4File = NULL;
2013         }
2014 
2015         // Change state
2016         SetState(EPVMFNodePrepared);
2017         status = PVMFSuccess;
2018     }
2019 
2020     if (PVMFSuccess == status)
2021     {
2022         iFileRendered = true;
2023     }
2024     return status;
2025 }
2026 
2027 //////////////////////////////////////////////////////////////////////////////////
DoFlush(PVMp4FFCNCmd & aCmd)2028 void PVMp4FFComposerNode::DoFlush(PVMp4FFCNCmd& aCmd)
2029 {
2030     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::DoFlush() iInterfaceState:%d", iInterfaceState));
2031 #ifdef _TEST_AE_ERROR_HANDLING
2032     if (FAIL_NODE_CMD_FLUSH == iErrorNodeCmd)
2033     {
2034         iInterfaceState = EPVMFNodeError;
2035     }
2036 #endif
2037     switch (iInterfaceState)
2038     {
2039         case EPVMFNodeStarted:
2040         case EPVMFNodePaused:
2041             int32 err;
2042             uint32 i;
2043             bool msgPending;
2044             msgPending = false;
2045 
2046             for (i = 0; i < iInPorts.size(); i++)
2047             {
2048                 if (iInPorts[i]->IncomingMsgQueueSize() > 0)
2049                     msgPending = true;
2050                 iInPorts[i]->SuspendInput();
2051                 if (iInterfaceState != EPVMFNodeStarted)
2052                 {
2053                     // Port is in idle if node state is not started. Call ProcessIncomingMsgReady
2054                     // to wake up port AO
2055                     ((PVMp4FFComposerPort*)iInPorts[i])->ProcessIncomingMsgReady();
2056                 }
2057             }
2058 
2059             // Move the command from the input command queue to the current command, where
2060             // it will remain until the flush completes.
2061             err = StoreCurrentCommand(iCurrentCmd, aCmd, iCmdQueue);
2062             if (0 != err)
2063                 return;
2064 
2065             iCmdQueue.Erase(&aCmd);
2066 
2067             if (!msgPending)
2068             {
2069                 FlushComplete();
2070                 return;
2071             }
2072             break;
2073 
2074         default:
2075             CommandComplete(iCmdQueue, aCmd, PVMFFailure);
2076             break;
2077     }
2078 }
2079 
2080 ////////////////////////////////////////////////////////////////////////////
IsFlushPending()2081 bool PVMp4FFComposerNode::IsFlushPending()
2082 {
2083     return (iCurrentCmd.size() > 0
2084             && iCurrentCmd.front().iCmd == PVMF_GENERIC_NODE_FLUSH);
2085 }
2086 
2087 ////////////////////////////////////////////////////////////////////////////
FlushComplete()2088 void PVMp4FFComposerNode::FlushComplete()
2089 {
2090     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::FlushComplete"));
2091     uint32 i = 0;
2092     PVMFStatus status = PVMFSuccess;
2093     // Flush is complete only when all queues of all ports are clear.
2094     // Other wise, just return from this method and wait for FlushComplete
2095     // from the remaining ports.
2096     for (i = 0; i < iInPorts.size(); i++)
2097     {
2098         if (iInPorts[i]->IncomingMsgQueueSize() > 0 ||
2099                 iInPorts[i]->OutgoingMsgQueueSize() > 0)
2100         {
2101             return;
2102         }
2103     }
2104 #ifdef ANDROID
2105     iFragmentWriter->flush();
2106 #endif
2107     if (!iNodeEndOfDataReached)
2108     {
2109         WriteDecoderSpecificInfo();
2110         // Finalize output file
2111         if (iSampleInTrack)
2112         {
2113             status = RenderToFile();
2114         }
2115 
2116         iSampleInTrack = false;
2117 
2118         if (status != PVMFSuccess)
2119             LOG_ERR((0, "PVMp4FFComposerNode::FlushComplete: Error - RenderToFile failed"));
2120     }
2121 
2122     // Resume port input so the ports can be re-started.
2123     for (i = 0; i < iInPorts.size(); i++)
2124         iInPorts[i]->ResumeInput();
2125 
2126     SetState(EPVMFNodePrepared);
2127 
2128     if (!iCurrentCmd.empty())
2129     {
2130         CommandComplete(iCurrentCmd, iCurrentCmd[0], status);
2131     }
2132 
2133     if (!iCmdQueue.empty())
2134     {
2135         // If command queue is not empty, schedule to process the next command
2136         RunIfNotReady();
2137     }
2138 
2139 
2140 }
2141 
2142 //////////////////////////////////////////////////////////////////////////////////
DoPause(PVMp4FFCNCmd & aCmd)2143 void PVMp4FFComposerNode::DoPause(PVMp4FFCNCmd& aCmd)
2144 {
2145     PVMFStatus status = PVMFSuccess;
2146 
2147 #ifdef _TEST_AE_ERROR_HANDLING
2148     if (FAIL_NODE_CMD_PAUSE == iErrorNodeCmd)
2149     {
2150         iInterfaceState = EPVMFNodeError;
2151     }
2152 #endif
2153     switch (iInterfaceState)
2154     {
2155         case EPVMFNodeStarted:
2156             SetState(EPVMFNodePaused);
2157             break;
2158         case EPVMFNodePaused:
2159             break;
2160         default:
2161             status = PVMFErrInvalidState;
2162             break;
2163     }
2164 
2165     CommandComplete(iCmdQueue, aCmd, status);
2166 }
2167 
2168 //////////////////////////////////////////////////////////////////////////////////
DoReset(PVMp4FFCNCmd & aCmd)2169 void PVMp4FFComposerNode::DoReset(PVMp4FFCNCmd& aCmd)
2170 {
2171     PVMFStatus status = PVMFSuccess;
2172 #if PROFILING_ON
2173     if (!oDiagnosticsLogged)
2174     {
2175         LogDiagnostics();
2176     }
2177 #endif
2178 
2179     if (IsAdded())
2180     {
2181         if (iSampleInTrack)
2182         {
2183             WriteDecoderSpecificInfo();
2184             status = RenderToFile();
2185             iSampleInTrack = false;
2186         }
2187 
2188         //delete all ports and notify observer.
2189         while (!iInPorts.empty())
2190             iInPorts.Erase(&iInPorts.front());
2191 
2192         //restore original port vector reserve.
2193         iInPorts.Reconstruct();
2194         iNodeEndOfDataReached = false;
2195 
2196         //logoff & go back to Created state.
2197         SetState(EPVMFNodeIdle);
2198         status = PVMFSuccess;
2199     }
2200     else
2201     {
2202         OSCL_LEAVE(OsclErrInvalidState);
2203     }
2204 
2205     CommandComplete(iCmdQueue, aCmd, status);
2206 }
2207 
2208 //////////////////////////////////////////////////////////////////////////////////
DoCancelAllCommands(PVMp4FFCNCmd & aCmd)2209 void PVMp4FFComposerNode::DoCancelAllCommands(PVMp4FFCNCmd& aCmd)
2210 {
2211     //first cancel the current command if any
2212     while (!iCurrentCmd.empty())
2213         CommandComplete(iCurrentCmd, iCurrentCmd[0], PVMFErrCancelled);
2214 
2215     //next cancel all queued commands
2216     //start at element 1 since this cancel command is element 0.
2217     while (iCmdQueue.size() > 1)
2218         CommandComplete(iCmdQueue, iCmdQueue[1], PVMFErrCancelled);
2219 
2220     //finally, report cancel complete.
2221     CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
2222 }
2223 
2224 //////////////////////////////////////////////////////////////////////////////////
DoCancelCommand(PVMp4FFCNCmd & aCmd)2225 void PVMp4FFComposerNode::DoCancelCommand(PVMp4FFCNCmd& aCmd)
2226 {
2227     //extract the command ID from the parameters.
2228     PVMFCommandId id;
2229     aCmd.Parse(id);
2230 
2231     //first check "current" command if any
2232     PVMp4FFCNCmd* cmd = iCurrentCmd.FindById(id);
2233     if (cmd)
2234     {
2235         //cancel the queued command
2236         CommandComplete(iCurrentCmd, *cmd, PVMFErrCancelled);
2237         //report cancel success
2238         CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
2239         return;
2240     }
2241 
2242     //next check input queue.
2243     //start at element 1 since this cancel command is element 0.
2244     cmd = iCmdQueue.FindById(id, 1);
2245     if (cmd)
2246     {
2247         //cancel the queued command
2248         CommandComplete(iCmdQueue, *cmd, PVMFErrCancelled);
2249         //report cancel success
2250         CommandComplete(iCmdQueue, aCmd, PVMFSuccess);
2251         return;
2252     }
2253 
2254     //if we get here the command isn't queued so the cancel fails.
2255     CommandComplete(iCmdQueue, aCmd, PVMFFailure);
2256 }
2257 
2258 //////////////////////////////////////////////////////////////////////////////////
2259 //                  Port activity processing routines
2260 //////////////////////////////////////////////////////////////////////////////////
IsProcessIncomingMsgReady()2261 bool PVMp4FFComposerNode::IsProcessIncomingMsgReady()
2262 {
2263     if (iInterfaceState == EPVMFNodeStarted || IsFlushPending())
2264         return true;
2265     else
2266         return false;
2267 }
2268 
2269 ////////////////////////////////////////////////////////////////////////////
ProcessIncomingMsg(PVMFPortInterface * aPort)2270 PVMFStatus PVMp4FFComposerNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
2271 {
2272     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::ProcessIncomingMsg: aPort=0x%x", aPort));
2273     PVMFStatus status = PVMFSuccess;
2274 
2275     switch (aPort->GetPortTag())
2276     {
2277         case PVMF_MP4FFCN_PORT_TYPE_SINK:
2278         {
2279             PVMp4FFComposerPort* port = OSCL_REINTERPRET_CAST(PVMp4FFComposerPort*, aPort);
2280             if (!IsProcessIncomingMsgReady())
2281             {
2282                 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - Not ready."));
2283                 return PVMFErrBusy;
2284             }
2285 
2286             PVMFSharedMediaMsgPtr msg;
2287             status = port->DequeueIncomingMsg(msg);
2288             if (status != PVMFSuccess)
2289             {
2290                 LOG_ERR((0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed"));
2291                 return status;
2292             }
2293             if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
2294             {
2295                 LOGDATATRAFFIC((0, "PVMp4FFComposerNode::ProcessIncomingMsg: EOS Recvd - TrackID=%d, StreamID=%d, TS=%d, Mime=%s",
2296                                 port->GetTrackId(), msg->getStreamID(), msg->getTimestamp(), port->GetMimeType().get_cstr()));
2297 
2298                 port->iEndOfDataReached = true;
2299                 //check if EOS has been received on all connected ports.
2300                 uint32 ii = 0;
2301                 iNodeEndOfDataReached = true;
2302                 for (ii = 0; ii < iInPorts.size(); ii++)
2303                 {
2304                     if (!iInPorts[ii]->iEndOfDataReached)
2305                     {
2306                         iNodeEndOfDataReached = false;
2307                     }
2308                 }
2309 
2310                 if (iNodeEndOfDataReached)
2311                 {
2312                     //Close the file since EOS is received on every connected port
2313                     WriteDecoderSpecificInfo();
2314                     if (iSampleInTrack)
2315                     {
2316                         status = RenderToFile();
2317                         iSampleInTrack = false;
2318                     }
2319 
2320                     //report EOS info to engine
2321                     ReportInfoEvent(PVMF_COMPOSER_EOS_REACHED);
2322                 }
2323 
2324                 //since we do not have data to process, we can safely break here.
2325                 break;
2326             }
2327 
2328             PVMFSharedMediaDataPtr mediaDataPtr;
2329             convertToPVMFMediaData(mediaDataPtr, msg);
2330 
2331             int32 trackId = port->GetTrackId();
2332             if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_M4V))
2333             {
2334                 // Set VOL Header
2335                 OsclRefCounterMemFrag volHeader;
2336                 if (mediaDataPtr->getFormatSpecificInfo(volHeader) == false ||
2337                         volHeader.getMemFragSize() == 0)
2338                 {
2339                     PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR,
2340                                     (0, "PVMp4FFComposerNode::ProcessIncomingMsg: Error - VOL Header not available"));
2341                     return PVMFFailure;
2342                 }
2343 
2344                 iMpeg4File->setDecoderSpecificInfo((uint8*)volHeader.getMemFragPtr(),
2345                                                    (int32)volHeader.getMemFragSize(), trackId);
2346             }
2347             if ((mediaDataPtr->getSeqNum() == 0) && (port->GetFormat() == PVMF_MIME_H264_VIDEO_MP4))
2348             {
2349                 iTrackId_H264 = port->GetTrackId();
2350                 iformat_h264 = port->GetFormat();
2351             }
2352             if (port->GetFormat() == PVMF_MIME_3GPP_TIMEDTEXT)
2353             {
2354                 iTrackId_Text = port->GetTrackId();
2355                 iformat_text = port->GetFormat();
2356                 GetTextSDIndex(mediaDataPtr->getSeqNum(), iText_sdIndex);
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                 WriteDecoderSpecificInfo();
3050                 iSampleInTrack = false;
3051                 if (RenderToFile() != PVMFSuccess)
3052                     return PVMFFailure;
3053             }
3054 
3055             ReportInfoEvent(PVMF_COMPOSER_MAXFILESIZE_REACHED, NULL);
3056             return PVMFSuccess;
3057 #endif
3058         }
3059 
3060         return PVMFPending;
3061     }
3062 
3063     return PVMFErrNotSupported;
3064 }
3065 
3066 //////////////////////////////////////////////////////////////////////////////////
CheckMaxDuration(uint32 aTimestamp)3067 PVMFStatus PVMp4FFComposerNode::CheckMaxDuration(uint32 aTimestamp)
3068 {
3069     //if(!iInfoObserver)
3070     //  return PVMFFailure;
3071 
3072     if (iMaxDurationEnabled)
3073     {
3074         if (aTimestamp >= iMaxTimeDuration)
3075         {
3076 #ifdef ANDROID
3077             // This code is executed on the fragment writer thread, we
3078             // don't want to call RenderToFile since it will call
3079             // flush() on the writer from this very same
3080             // thread. Instead, we use a marker to report an event to
3081             // the author node next time a new fragment is processed.
3082             iMaxReachedEvent = PVMF_COMPOSER_MAXDURATION_REACHED;
3083 #else
3084 
3085             // Finalize output file
3086             if (iSampleInTrack)
3087             {
3088                 WriteDecoderSpecificInfo();
3089                 iSampleInTrack = false;
3090                 if (RenderToFile() != PVMFSuccess)
3091                     return PVMFFailure;
3092             }
3093 
3094             ReportInfoEvent(PVMF_COMPOSER_MAXDURATION_REACHED, NULL);
3095             return PVMFSuccess;
3096 #endif
3097         }
3098 
3099         return PVMFPending;
3100     }
3101 
3102     return PVMFErrNotSupported;
3103 }
3104 
3105 ////////////////////////////////////////////////////////////////////////////
3106 //                   Event reporting routines.
3107 ////////////////////////////////////////////////////////////////////////////
SetState(TPVMFNodeInterfaceState aState)3108 void PVMp4FFComposerNode::SetState(TPVMFNodeInterfaceState aState)
3109 {
3110     LOG_STACK_TRACE((0, "PVMp4FFComposerNode::SetState: aState=%d", aState));
3111     PVMFNodeInterface::SetState(aState);
3112 }
3113 
ReportErrorEvent(PvmfMp4FFCNError aErrorEvent,OsclAny * aEventData)3114 void PVMp4FFComposerNode::ReportErrorEvent(PvmfMp4FFCNError aErrorEvent, OsclAny* aEventData)
3115 {
3116     LOG_ERR((0, "PVMp4FFComposerNode:ReportErrorEvent: aEventType=%d, aEventData=0x%x", aErrorEvent, aEventData));
3117     switch (aErrorEvent)
3118     {
3119         case PVMF_MP4FFCN_ERROR_FINALIZE_OUTPUT_FILE_FAILED:
3120         case PVMF_MP4FFCN_ERROR_ADD_SAMPLE_TO_TRACK_FAILED:
3121             PVMFNodeInterface::ReportErrorEvent(PVMFErrResourceConfiguration, aEventData);
3122             break;
3123         default:
3124             PVMFNodeInterface::ReportErrorEvent(PVMFFailure, aEventData);
3125             break;
3126     }
3127 }
3128 
ReportInfoEvent(PVMFEventType aEventType,OsclAny * aEventData)3129 void PVMp4FFComposerNode::ReportInfoEvent(PVMFEventType aEventType, OsclAny* aEventData)
3130 {
3131     LOG_STACK_TRACE((0, "PVMp4FFComposerNode:ReportInfoEvent: aEventType=%d, aEventData=0x%x", aEventType, aEventData));
3132     PVMFNodeInterface::ReportInfoEvent(aEventType, aEventData);
3133 }
3134 
3135 
3136 
LogDiagnostics()3137 void PVMp4FFComposerNode::LogDiagnostics()
3138 {
3139 #if PROFILING_ON
3140     oDiagnosticsLogged = true;
3141     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));
3142 #endif
3143 }
3144 
StoreCurrentCommand(PVMp4FFCNCmdQueue & aCurrentCmd,PVMp4FFCNCmd & aCmd,PVMp4FFCNCmdQueue & aCmdQueue)3145 int32 PVMp4FFComposerNode::StoreCurrentCommand(PVMp4FFCNCmdQueue& aCurrentCmd, PVMp4FFCNCmd& aCmd, PVMp4FFCNCmdQueue& aCmdQueue)
3146 {
3147     int32 err = 0;
3148     OSCL_TRY(err, aCurrentCmd.StoreL(aCmd););
3149     OSCL_FIRST_CATCH_ANY(err,
3150                          CommandComplete(aCmdQueue, aCmd, PVMFErrNoMemory);
3151                          return err;
3152                         );
3153     return err;
3154 }
3155 
GetTextSDIndex(uint32 aSampleNum,int32 & aIndex)3156 void PVMp4FFComposerNode::GetTextSDIndex(uint32 aSampleNum, int32& aIndex)
3157 {
3158     //default index is zero
3159     aIndex = 0;
3160     Oscl_Vector<PVA_FF_TextSampleDescInfo*, OsclMemAllocator>::iterator it;
3161     for (it = textdecodervector.begin(); it != textdecodervector.end(); it++)
3162     {
3163         if ((aSampleNum >= (*it)->start_sample_num) &&
3164                 (aSampleNum <= (*it)->end_sample_num))
3165         {
3166             aIndex = (*it)->sdindex;
3167             break;
3168         }
3169     }
3170 }
3171 
3172 
3173 
3174