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