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