OSDN Git Service

96ac93a3b46f74e3f5a176d2ae47e3d0134a1006
[android-x86/external-opencore.git] / nodes / pvomxaudiodecnode / src / pvmf_omx_audiodec_node.cpp
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2010 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "pvmf_omx_audiodec_node.h"
19 #include "oscl_string_utils.h"
20
21 #define CONFIG_SIZE_AND_VERSION(param) \
22         param.nSize=sizeof(param); \
23         param.nVersion.s.nVersionMajor = SPECVERSIONMAJOR; \
24         param.nVersion.s.nVersionMinor = SPECVERSIONMINOR; \
25         param.nVersion.s.nRevision = SPECREVISION; \
26         param.nVersion.s.nStep = SPECSTEP;
27
28
29
30 #define PVOMXAUDIODEC_MEDIADATA_POOLNUM 2*NUMBER_OUTPUT_BUFFER
31 #define PVOMXAUDIODEC_MEDIADATA_CHUNKSIZE 128
32
33
34 // Node default settings
35
36 #define PVOMXAUDIODECNODE_CONFIG_MIMETYPE_DEF 0
37
38 #define PVMF_OMXAUDIODEC_NUM_METADATA_VALUES 6
39
40
41
42 // Constant character strings for metadata keys
43 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY[] = "codec-info/audio/format";
44 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY[] = "codec-info/audio/channels";
45 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY[] = "codec-info/audio/sample-rate";
46 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_AVGBITRATE_KEY[] = "codec-info/audio/avgbitrate";
47 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_AACOBJECTTYPE_KEY[] = "codec-info/audio/aac-objecttype";
48 static const char PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_AACSTREAMTYPE_KEY[] = "codec-info/audio/aac-streamtype";
49
50
51 static const char PVOMXAUDIODECMETADATA_SEMICOLON[] = ";";
52
53 /////////////////////////////////////////////////////////////////////////////
54 // Class Destructor
55 /////////////////////////////////////////////////////////////////////////////
56 PVMFOMXAudioDecNode::~PVMFOMXAudioDecNode()
57 {
58     DeleteLATMParser();
59     ReleaseAllPorts();
60     iGaplessLogger = NULL;
61 }
62
63 // Class Constructor
64 PVMFOMXAudioDecNode::PVMFOMXAudioDecNode(int32 aPriority) :
65         PVMFOMXBaseDecNode(aPriority, "PVMFOMXAudioDecNode")
66 {
67     iInterfaceState = EPVMFNodeCreated;
68
69     iNodeConfig.iMimeType = PVOMXAUDIODECNODE_CONFIG_MIMETYPE_DEF;
70
71
72     int32 err;
73     OSCL_TRY(err,
74
75              //Create the input command queue.  Use a reserve to avoid lots of
76              //dynamic memory allocation.
77              iInputCommands.Construct(PVMF_OMXBASEDEC_NODE_COMMAND_ID_START, PVMF_OMXBASEDEC_NODE_COMMAND_VECTOR_RESERVE);
78
79              //Set the node capability data.
80              //This node can support an unlimited number of ports.
81              iCapability.iCanSupportMultipleInputPorts = false;
82              iCapability.iCanSupportMultipleOutputPorts = false;
83              iCapability.iHasMaxNumberOfPorts = true;
84              iCapability.iMaxNumberOfPorts = 2;
85              iCapability.iInputFormatCapability.push_back(PVMF_MIME_MPEG4_AUDIO);
86              iCapability.iInputFormatCapability.push_back(PVMF_MIME_3640);
87              iCapability.iInputFormatCapability.push_back(PVMF_MIME_ADIF);
88              iCapability.iInputFormatCapability.push_back(PVMF_MIME_LATM);
89              iCapability.iInputFormatCapability.push_back(PVMF_MIME_ASF_MPEG4_AUDIO);
90              iCapability.iInputFormatCapability.push_back(PVMF_MIME_AAC_SIZEHDR);
91
92              iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IF2);
93              iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR_IETF);
94              iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMR);
95              iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB_IETF);
96              iCapability.iInputFormatCapability.push_back(PVMF_MIME_AMRWB);
97
98              iCapability.iInputFormatCapability.push_back(PVMF_MIME_MP3);
99
100              iCapability.iInputFormatCapability.push_back(PVMF_MIME_WMA);
101
102              iCapability.iInputFormatCapability.push_back(PVMF_MIME_REAL_AUDIO);
103
104              iCapability.iOutputFormatCapability.push_back(PVMF_MIME_PCM16);
105
106              iAvailableMetadataKeys.reserve(PVMF_OMXAUDIODEC_NUM_METADATA_VALUES);
107              iAvailableMetadataKeys.clear();
108             );
109     // LATM init
110     iLATMParser = NULL;
111     iLATMConfigBuffer = NULL;
112     iLATMConfigBufferSize = 0;
113
114     iCountSamplesInBuffer = false;
115     iBufferContainsIntFrames = true;
116
117     iComputeSamplesPerFrame = true;
118
119     // This default value can be changed using cap-config
120     iOutputBufferPCMDuration = PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME; // set PCM buffer duration to default (200ms)
121
122
123     //Try Allocate FSI buffer
124
125     // Do This first in case of Query
126     OSCL_TRY(err, iFsiFragmentAlloc.size(PVOMXAUDIODEC_MEDIADATA_POOLNUM, sizeof(channelSampleInfo)));
127
128
129     OSCL_TRY(err, iPrivateDataFsiFragmentAlloc.size(PVOMXAUDIODEC_MEDIADATA_POOLNUM, sizeof(OsclAny *)));
130
131     iLogger = PVLogger::GetLoggerObject("PVMFOMXAudioDecNode");
132     iRunlLogger = PVLogger::GetLoggerObject("Run.PVMFOMXAudioDecNode");
133     iDataPathLogger = PVLogger::GetLoggerObject("datapath");
134     iClockLogger = PVLogger::GetLoggerObject("clock");
135     iDiagnosticsLogger = PVLogger::GetLoggerObject("pvplayerdiagnostics.decnode.OMXAudioDecnode");
136     iGaplessLogger = PVLogger::GetLoggerObject("gapless.decnode");
137 }
138
139
140 // this is a utility possibly called multiple times by ProcessIncomingMsg method
141 // it returns PVMFSuccess if the msg is a cmd msg and is processed
142 // PVMFFailure if the msg is a cmd msg, but cannot be processed correctly
143 // PVMFPending if the msg is a data msg
144 PVMFStatus PVMFOMXAudioDecNode::CheckIfIncomingMsgIsCmd(PVMFSharedMediaMsgPtr msg)
145 {
146
147     PVMFStatus status = PVMFPending; // assume this is a data message
148
149     if (msg->getFormatID() == PVMF_MEDIA_CMD_BOS_FORMAT_ID)
150     {
151         //store the stream id and time stamp of bos message
152         iStreamID = msg->getStreamID();
153         iCurrentClipId = msg->getClipID();
154
155         iClipSampleCount = 0;
156
157         iSendBOS = true;
158
159         // if new BOS arrives, and
160         //if we're in the middle of a partial frame assembly
161         // abandon it and start fresh
162         if (iObtainNewInputBuffer == false)
163         {
164             if (iInputBufferUnderConstruction != NULL)
165             {
166                 if (iInBufMemoryPool != NULL)
167                 {
168                     iInBufMemoryPool->deallocate((OsclAny *)(iInputBufferUnderConstruction->pMemPoolEntry));
169                 }
170                 iInputBufferUnderConstruction = NULL;
171             }
172             iObtainNewInputBuffer = true;
173
174         }
175
176         // needed to init the sequence numbers and timestamp for partial frame assembly
177         iFirstDataMsgAfterBOS = true;
178         iKeepDroppingMsgsUntilMarkerBit = false;
179
180         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
181                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received BOS stream %d, clipId %d", iStreamID, iCurrentClipId));
182
183         status = PVMFSuccess;
184     }
185     else if (msg->getFormatID() == PVMF_MEDIA_CMD_EOS_FORMAT_ID)
186     {
187         // Set EOS flag
188         iEndOfDataReached = true;
189         // Save the timestamp for the EOS cmd
190         iEndOfDataTimestamp = msg->getTimestamp();
191         iCurrentClipId = msg->getClipID();
192
193         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
194                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received EOS clipId %d", iCurrentClipId));
195
196
197         status = PVMFSuccess;
198     }
199     else if (msg->getFormatID() == PVMF_MEDIA_CMD_BOC_FORMAT_ID)
200     {
201         // get pointer to the data fragment
202         OsclRefCounterMemFrag DataFrag;
203         msg->getFormatSpecificInfo(DataFrag);
204
205         // get format specific info
206         BOCInfo* bocInfoPtr = (BOCInfo*)DataFrag.getMemFragPtr();
207         int32 bocInfoSize = (int32)DataFrag.getMemFragSize();
208         OSCL_UNUSED_ARG(bocInfoSize); // bocInfoSize is used only for logging
209         if (bocInfoPtr == NULL)
210         {
211             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
212                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received BOC, memFragPtr %x, memFragSize %d, but memFragPtr is NULL",
213                              bocInfoPtr, bocInfoSize));
214
215             return PVMFFailure;
216         }
217
218         iBOCSamplesToSkip = bocInfoPtr->samplesToSkip;
219         iBOCTimeStamp = msg->getTimestamp();
220         iBOCReceived = true;
221
222         if (iNodeConfig.iMimeType == PVMF_MIME_MP3)
223         {
224             iBOCSamplesToSkip += MP3_DECODER_DELAY;
225         }
226
227         CalculateBOCParameters();
228
229         // only count samples if there is gapless metadata (i.e. BOC is sent)
230         iCountSamplesInBuffer = true;
231         iClipSampleCount = 0;
232
233         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
234                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received BOC, memFragPtr %x, memFragSize %d, samplesToSkipBOC %d",
235                          bocInfoPtr, bocInfoSize, bocInfoPtr->samplesToSkip));
236
237         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iGaplessLogger, PVLOGMSG_INFO,
238                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg() Gapless BOC, bocInfoPtr->samplesToSkip %d, iBOCSamplesToSkip %d",
239                          bocInfoPtr->samplesToSkip, iBOCSamplesToSkip));
240
241         status = PVMFSuccess;
242     }
243     else if (msg->getFormatID() == PVMF_MEDIA_CMD_EOC_FORMAT_ID)
244     {
245         // get pointer to the data fragment
246         OsclRefCounterMemFrag DataFrag;
247         msg->getFormatSpecificInfo(DataFrag);
248
249         // get format specific info
250         EOCInfo* eocInfoPtr = (EOCInfo*)DataFrag.getMemFragPtr();
251         int32 eocInfoSize = (int32)DataFrag.getMemFragSize();
252         OSCL_UNUSED_ARG(eocInfoSize); // eocInfoSize is used only for logging
253
254         if (eocInfoPtr == NULL)
255         {
256             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
257                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received EOC, memFragPtr %x, memFragSize %d, but memFragPtr is NULL",
258                              eocInfoPtr, eocInfoSize));
259
260             return PVMFFailure;
261         }
262
263         iEOCSamplesToSkip = eocInfoPtr->samplesToSkip;
264         iEOCFramesToFollow = eocInfoPtr->framesToFollow;
265         iEOCTimeStamp = msg->getTimestamp();
266         iEOCReceived = true;
267
268         if (iNodeConfig.iMimeType == PVMF_MIME_MP3)
269         {
270             iEOCSamplesToSkip -= OSCL_MIN(MP3_DECODER_DELAY, iEOCSamplesToSkip);
271         }
272
273         CalculateEOCParameters();
274
275         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
276                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: Received EOC, memFragPtr %x, memFragSize %d, framesToFollowEOC % d, samplesToSkipEOC %d",
277                          eocInfoPtr, eocInfoSize, eocInfoPtr->samplesToSkip, eocInfoPtr->framesToFollow));
278
279         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iGaplessLogger, PVLOGMSG_INFO,
280                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg() Gapless EOC, framesToFollowEOC %d, eocInfoPtr->samplesToSkip %d, iEOCSamplesToSkip %d",
281                          iEOCFramesToFollow, eocInfoPtr->samplesToSkip, iEOCSamplesToSkip));
282
283
284         status = PVMFSuccess;
285     }
286
287     return status;
288
289 }
290 /////////////////////////////////////////////////////////////////////////////
291 // This routine will process incomming message from the port
292 /////////////////////////////////////////////////////////////////////////////
293 bool PVMFOMXAudioDecNode::ProcessIncomingMsg(PVMFPortInterface* aPort)
294 {
295     //Called by the AO to process one buffer off the port's
296     //incoming data queue.  This routine will dequeue and
297     //dispatch the data.
298
299     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
300                     (0, "0x%x PVMFOMXAudioDecNode::ProcessIncomingMsg: aPort=0x%x", this, aPort));
301
302     PVMFStatus status = PVMFFailure;
303 #ifdef SIMULATE_DROP_MSGS
304     if ((((PVMFOMXDecPort*)aPort)->iNumFramesConsumed % 300 == 299))  // && (((PVMFOMXDecPort*)aPort)->iNumFramesConsumed < 30) )
305     {
306
307         // just dequeue
308         PVMFSharedMediaMsgPtr msg;
309
310         status = aPort->DequeueIncomingMsg(msg);
311         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
312         status = aPort->DequeueIncomingMsg(msg);
313         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
314         status = aPort->DequeueIncomingMsg(msg);
315         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
316
317 #ifdef _DEBUG
318         printf("PVMFOMXAudioDecNode::ProcessIncomingMsg() SIMULATED DROP 3 MSGS\n");
319 #endif
320
321
322     }
323 #endif
324
325 #ifdef SIMULATE_BOS
326
327     if ((((PVMFOMXDecPort*)aPort)->iNumFramesConsumed == 6))
328     {
329
330         PVMFSharedMediaCmdPtr BOSCmdPtr = PVMFMediaCmd::createMediaCmd();
331
332         // Set the format ID to BOS
333         BOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);
334
335         // Set the timestamp
336         BOSCmdPtr->setTimestamp(201);
337         BOSCmdPtr->setStreamID(0);
338
339         // Convert to media message and send it out
340         PVMFSharedMediaMsgPtr mediaMsgOut;
341         convertToPVMFMediaCmdMsg(mediaMsgOut, BOSCmdPtr);
342
343         //store the stream id bos message
344         iStreamID = mediaMsgOut->getStreamID();
345
346         iSendBOS = true;
347
348 #ifdef _DEBUG
349         printf("PVMFOMXAudioDecNode::ProcessIncomingMsg() SIMULATED BOS\n");
350 #endif
351         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
352         return true;
353
354     }
355 #endif
356
357 #ifdef SIMULATE_PREMATURE_EOS
358     if (((PVMFOMXDecPort*)aPort)->iNumFramesConsumed == 5)
359     {
360         PVMFSharedMediaCmdPtr EOSCmdPtr = PVMFMediaCmd::createMediaCmd();
361
362         // Set the format ID to EOS
363         EOSCmdPtr->setFormatID(PVMF_MEDIA_CMD_EOS_FORMAT_ID);
364
365         // Set the timestamp
366         EOSCmdPtr->setTimestamp(200);
367
368         // Convert to media message and send it out
369         PVMFSharedMediaMsgPtr mediaMsgOut;
370         convertToPVMFMediaCmdMsg(mediaMsgOut, EOSCmdPtr);
371
372         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
373
374         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
375                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: SIMULATED EOS"));
376 #ifdef _DEBUG
377         printf("PVMFOMXAudioDecNode::ProcessIncomingMsg() SIMULATED EOS\n");
378 #endif
379         // Set EOS flag
380         iEndOfDataReached = true;
381         // Save the timestamp for the EOS cmd
382         iEndOfDataTimestamp = mediaMsgOut->getTimestamp();
383
384         return true;
385     }
386
387 #endif
388
389
390
391     PVMFSharedMediaMsgPtr msg;
392
393     status = aPort->DequeueIncomingMsg(msg);
394     if (status != PVMFSuccess)
395     {
396         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
397                         (0, "0x%x PVMFOMXAudioDecNode::ProcessIncomingMsg: Error - DequeueIncomingMsg failed", this));
398         return false;
399     }
400
401
402     // check if incoming msg is a cmd msg
403     status = CheckIfIncomingMsgIsCmd(msg);
404     if (PVMFSuccess == status)
405     {
406         // if a cmd msg, it was processed inside a helper method above
407         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
408         return true;
409     }
410     else if (PVMFFailure == status)
411     {
412         // something went wrong when processing the msg
413         return false;
414     }
415
416     // if we end up here, the msg is a data message
417
418
419
420     ///////////////////////////////////////////////////////////////////////////////////////
421     ///////////////////////////////////////////////////////////////////////
422     // For LATM data, need to convert to raw bitstream
423     if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM)
424     {
425         // Keep looping and parsing LATM data until frame complete or data queue runs out
426         uint8 retval; //=FRAME_INCOMPLETE;
427         // if LATM parser does not exist (very first frame), create it:
428         if (iLATMParser == NULL)
429         {
430             // Create and configure the LATM parser based on the stream MUX config
431             // which should be sent as the format specific config in the first media data
432             if (CreateLATMParser() != PVMFSuccess)
433             {
434
435                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
436                                 (0, "PVMFOMXAudioDecNode::Process Incoming Msg - LATM parser cannot be created"));
437                 OSCL_ASSERT(false);
438                 ReportErrorEvent(PVMFErrResourceConfiguration);
439                 ChangeNodeState(EPVMFNodeError);
440                 return true;
441             }
442
443             // get FSI
444             OsclRefCounterMemFrag DataFrag;
445             msg->getFormatSpecificInfo(DataFrag);
446
447             //get pointer to the data fragment
448             uint8* initbuffer = (uint8 *) DataFrag.getMemFragPtr();
449             uint32 initbufsize = (int32) DataFrag.getMemFragSize();
450
451             iLATMConfigBufferSize = initbufsize;
452             iLATMConfigBuffer = iLATMParser->ParseStreamMuxConfig(initbuffer, (int32 *) & iLATMConfigBufferSize);
453             if (iLATMConfigBuffer == NULL)
454             {
455                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
456                                 (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg() LATM Stream MUX config parsing failed"));
457                 OSCL_ASSERT(false);
458                 ReportErrorEvent(PVMFErrResourceConfiguration);
459                 ChangeNodeState(EPVMFNodeError);
460                 return true;
461             }
462
463         }
464
465         do
466         {
467
468             // if we end up here, the msg is a data message
469
470             // Convert the next input media msg to media data
471             PVMFSharedMediaDataPtr mediaData;
472             convertToPVMFMediaData(mediaData, msg);
473
474
475             ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
476
477             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iDataPathLogger, PVLOGMSG_INFO,
478                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: TS=%d, SEQNUM= %d", msg->getTimestamp(), msg->getSeqNum()));
479
480
481             // Convert the LATM data to raw bitstream
482             retval = iLATMParser->compose(mediaData);
483
484             // if frame is complete, break out of the loop
485             if (retval != FRAME_INCOMPLETE && retval != FRAME_ERROR)
486                 break;
487
488             // Log parser error
489             if (retval == FRAME_ERROR)
490             {
491                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
492                                 (0, "PVMFAACDecNode::GetInputMediaData() LATM parser error"));
493             }
494
495             // frame is not complete, keep looping
496             if (aPort->IncomingMsgQueueSize() == 0)
497             {
498                 // no more data in the input port queue, unbind current msg, and return
499                 msg.Unbind();
500                 // enable reading more data from port
501                 break;
502             }
503             else
504             {
505                 msg.Unbind();
506                 aPort->DequeueIncomingMsg(msg); // dequeue the message directly from input port
507
508             }
509
510             // check if incoming msg is a cmd msg
511             status = CheckIfIncomingMsgIsCmd(msg);
512             if (PVMFSuccess == status)
513             {
514                 // if a cmd msg, it was processed inside a helper method above
515                 ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
516                 return true;
517             }
518             else if (PVMFFailure == status)
519             {
520                 // something went wrong when processing the msg
521                 return false;
522             }
523
524         }
525         while ((retval == FRAME_INCOMPLETE || retval == FRAME_ERROR));
526
527         if (retval == FRAME_COMPLETE)
528         {
529             // Save the media data containing the parser data as the input media data
530             iDataIn = iLATMParser->GetOutputBuffer();
531             // set the MARKER bit on the data msg, since this is a complete frame produced by LATM parser
532             iDataIn->setMarkerInfo(PVMF_MEDIA_DATA_MARKER_INFO_M_BIT);
533             PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO,
534                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: - LATM frame assembled"));
535
536         }
537         else if ((retval == FRAME_INCOMPLETE) || (retval == FRAME_ERROR))
538         {
539             // Do nothing and wait for more data to come in
540             PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO,
541                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: - incomplete LATM"));
542             // return immediately (i.e. don't assign anything to iDataIn, which will prevent
543             // processing
544             return true;
545         }
546         else if (retval == FRAME_OUTPUTNOTAVAILABLE)
547         {
548             // This should not happen since this node processes one parsed media data at a time
549             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
550                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: LATM parser OUTPUT NOT AVAILABLE"));
551
552             msg.Unbind();
553
554             OSCL_ASSERT(false);
555             ReportErrorEvent(PVMFErrResourceConfiguration);
556             ChangeNodeState(EPVMFNodeError);
557
558             return true;
559         }
560     }
561 /////////////////////////////////////////////////////////
562     //////////////////////////
563     else
564     {
565         // regular (i.e. Non-LATM case)
566         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iDataPathLogger, PVLOGMSG_INFO,
567                         (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: TS=%d, SEQNUM= %d", msg->getTimestamp(), msg->getSeqNum()));
568
569         if (iFirstDataMsgAfterBOS)
570         {
571             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iDataPathLogger, PVLOGMSG_INFO,
572                             (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg: iTSOfFirstDataMsgAfterBOS = %d", msg->getTimestamp()));
573             iTSOfFirstDataMsgAfterBOS = msg->getTimestamp();
574             iInputTimestampClock.set_clock(iTSOfFirstDataMsgAfterBOS, 0);
575         }
576         convertToPVMFMediaData(iDataIn, msg);
577         ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed++;
578     }
579
580     iCurrFragNum = 0; // for new message, reset the fragment counter
581     iIsNewDataFragment = true;
582
583
584     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::ProcessIncomingMsg() Received %d frames", ((PVMFOMXDecPort*)aPort)->iNumFramesConsumed));
585
586     //return true if we processed an activity...
587     return true;
588 }
589
590 /////////////////////////////////////////////////////////////////////////////
591 // This routine will handle the PortReEnable state
592 /////////////////////////////////////////////////////////////////////////////
593 PVMFStatus PVMFOMXAudioDecNode::HandlePortReEnable()
594 {
595     OMX_ERRORTYPE Err;
596     // set the port index so that we get parameters for the proper port
597     iParamPort.nPortIndex = iPortIndexForDynamicReconfig;
598
599     CONFIG_SIZE_AND_VERSION(iParamPort);
600
601     // get new parameters of the port
602     Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
603     if (Err != OMX_ErrorNone)
604     {
605         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
606                         (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Problem getting parameters at port %d", iPortIndexForDynamicReconfig));
607
608         SetState(EPVMFNodeError);
609         ReportErrorEvent(PVMFErrResource);
610         return PVMFErrResource;
611     }
612
613     // send command for port re-enabling (for this to happen, we must first recreate the buffers)
614     Err = OMX_SendCommand(iOMXDecoder, OMX_CommandPortEnable, iPortIndexForDynamicReconfig, NULL);
615     if (Err != OMX_ErrorNone)
616     {
617         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
618                         (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> problem sending Port Enable command at port %d", iPortIndexForDynamicReconfig));
619
620         SetState(EPVMFNodeError);
621         ReportErrorEvent(PVMFErrResource);
622         return PVMFErrResource;
623     }
624
625
626     // get also input info (for frame duration if necessary)
627     OMX_PTR CodecProfilePtr;
628     OMX_INDEXTYPE CodecProfileIndx;
629     OMX_AUDIO_PARAM_AACPROFILETYPE Audio_Aac_Param;
630     OMX_AUDIO_PARAM_RATYPE Audio_Ra_Param;
631
632     // determine the proper index and structure (based on codec type)
633     if (iInPort)
634     {
635         // AAC
636         if (((PVMFOMXDecPort*)iInPort)->iFormat ==  PVMF_MIME_MPEG4_AUDIO ||
637                 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640 ||
638                 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM ||
639                 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF ||
640                 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO ||
641                 ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AAC_SIZEHDR) // for testing
642         {
643             CodecProfilePtr = (OMX_PTR) & Audio_Aac_Param;
644             CodecProfileIndx = OMX_IndexParamAudioAac;
645             Audio_Aac_Param.nPortIndex = iInputPortIndex;
646
647             CONFIG_SIZE_AND_VERSION(Audio_Aac_Param);
648
649
650             // get parameters:
651             Err = OMX_GetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr);
652             if (Err != OMX_ErrorNone)
653             {
654                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
655                                 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Input port parameters problem"));
656
657                 SetState(EPVMFNodeError);
658                 ReportErrorEvent(PVMFErrResource);
659                 return PVMFErrResource;
660             }
661         }
662         else if (((PVMFOMXDecPort*)iInPort)->iFormat ==  PVMF_MIME_REAL_AUDIO)
663         {
664             CodecProfilePtr = (OMX_PTR) & Audio_Ra_Param;
665             CodecProfileIndx = OMX_IndexParamAudioRa;
666             Audio_Ra_Param.nPortIndex = iInputPortIndex;
667
668             CONFIG_SIZE_AND_VERSION(Audio_Ra_Param);
669
670
671             // get parameters:
672             Err = OMX_GetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr);
673             if (Err != OMX_ErrorNone)
674             {
675                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
676                                 (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Input port parameters problem"));
677
678                 SetState(EPVMFNodeError);
679                 ReportErrorEvent(PVMFErrResource);
680                 return PVMFErrResource;
681             }
682         }
683         // for AMR, frame sizes are known, no need to get the parameters
684         // for MP3, frame sizes cannot be obtained through OMX params
685         // for WMA, frame sizes cannot be obtained through OMX params
686     }
687
688
689
690     PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN;
691     if (iInPort != NULL)
692     {
693         Format = ((PVMFOMXDecPort*)iInPort)->iFormat;
694     }
695     if (Format ==  PVMF_MIME_MPEG4_AUDIO ||
696             Format == PVMF_MIME_3640 ||
697             Format == PVMF_MIME_LATM ||
698             Format == PVMF_MIME_ADIF ||
699             Format == PVMF_MIME_ASF_MPEG4_AUDIO ||
700             Format == PVMF_MIME_AAC_SIZEHDR) // for testing
701     {
702         iSamplesPerFrame = Audio_Aac_Param.nFrameLength;
703     }
704     // AMR
705     else if (Format == PVMF_MIME_AMR_IF2 ||
706              Format == PVMF_MIME_AMR_IETF ||
707              Format == PVMF_MIME_AMR)
708     {
709         // AMR NB has fs=8khz Mono and the frame is 20ms long, i.e. there is 160 samples per frame
710         iSamplesPerFrame = PVOMXAUDIODEC_AMRNB_SAMPLES_PER_FRAME;
711     }
712     else if (Format == PVMF_MIME_AMRWB_IETF ||
713              Format == PVMF_MIME_AMRWB)
714     {
715         // AMR WB has fs=16khz Mono and the frame is 20ms long, i.e. there is 320 samples per frame
716         iSamplesPerFrame = PVOMXAUDIODEC_AMRWB_SAMPLES_PER_FRAME;
717     }
718     else if (Format == PVMF_MIME_MP3)
719     {
720         // frame size is either 576 or 1152 samples per frame. However, this information cannot be
721         // obtained through OMX MP3 Params. Assume that it's 1152
722         iSamplesPerFrame = PVOMXAUDIODEC_MP3_DEFAULT_SAMPLES_PER_FRAME;
723     }
724     else if (Format == PVMF_MIME_WMA)
725     {
726         // output frame size is unknown in WMA. However, the PV-WMA decoder can control the number
727         // of samples it places in an output buffer, so we can create an output buffer of arbitrary size
728         // and let the decoder control how it is filled
729         iSamplesPerFrame = 0; // unknown
730     }
731     else if (Format == PVMF_MIME_REAL_AUDIO)
732     {
733         iSamplesPerFrame = Audio_Ra_Param.nSamplePerFrame;
734     }
735
736
737     // is this output port?
738     if (iPortIndexForDynamicReconfig == iOutputPortIndex)
739     {
740
741         // GET the output buffer params and sizes
742         OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param;
743         Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params
744
745         CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param);
746
747
748
749         Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param);
750         if (Err != OMX_ErrorNone)
751         {
752             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
753                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot get component output parameters"));
754
755             SetState(EPVMFNodeError);
756             ReportErrorEvent(PVMFErrResource);
757             return PVMFErrResource;
758         }
759
760         iPCMSamplingRate = Audio_Pcm_Param.nSamplingRate; // can be set to 0 (if unknown)
761
762         if (iPCMSamplingRate == 0) // use default sampling rate (i.e. 48000)
763             iPCMSamplingRate = PVOMXAUDIODEC_DEFAULT_SAMPLINGRATE;
764
765         iNumberOfAudioChannels = Audio_Pcm_Param.nChannels;     // should be 1 or 2
766         if (iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2)
767         {
768             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
769                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Output parameters num channels = %d", iNumberOfAudioChannels));
770
771             SetState(EPVMFNodeError);
772             ReportErrorEvent(PVMFErrResource);
773             return PVMFErrResource;
774         }
775
776         if ((iSamplesPerFrame != 0) && ((iSamplesPerFrame * 1000) > iPCMSamplingRate))
777             // if this iSamplesPerFrame is known and is large enough to ensure that the iMilliSecPerFrame calculation
778             // below won't be set to 0.
779         {
780             // CALCULATE NumBytes per frame, Msec per frame, etc.
781             iNumBytesPerFrame = 2 * iSamplesPerFrame * iNumberOfAudioChannels;
782             iMilliSecPerFrame = (iSamplesPerFrame * 1000) / iPCMSamplingRate;
783             // Determine the size of each PCM output buffer. Size would be big enough to hold certain time amount of PCM data
784             uint32 numframes = iOutputBufferPCMDuration / iMilliSecPerFrame;
785
786             if (iOutputBufferPCMDuration % iMilliSecPerFrame)
787             {
788                 // If there is a remainder, include one more frame
789                 ++numframes;
790             }
791
792             // set the output buffer size accordingly:
793             iOMXComponentOutputBufferSize = numframes * iNumBytesPerFrame;
794         }
795         else
796             iOMXComponentOutputBufferSize = (2 * iNumberOfAudioChannels * iOutputBufferPCMDuration * iPCMSamplingRate) / 1000; // assuming 16 bits per sample
797
798         if (iOMXComponentOutputBufferSize < iParamPort.nBufferSize)
799         {
800             // the OMX spec says that nBuffersize is a read only field, but the client is allowed to allocate
801             // a buffer size larger than nBufferSize.
802             iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
803         }
804
805         if (iBOCReceived)
806             CalculateBOCParameters();
807
808         if (iEOCReceived)
809             CalculateEOCParameters();
810
811         // read the alignment again - just in case
812         iOutputBufferAlignment = iParamPort.nBufferAlignment;
813
814         iNumOutputBuffers = iParamPort.nBufferCountActual;
815
816         if (iNumOutputBuffers > NUMBER_OUTPUT_BUFFER)
817             iNumOutputBuffers = NUMBER_OUTPUT_BUFFER; // make sure number of output buffers is not larger than port queue size
818
819         // do we need to increase the number of buffers?
820         if (iNumOutputBuffers < iParamPort.nBufferCountMin)
821             iNumOutputBuffers = iParamPort.nBufferCountMin;
822
823         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
824                         (0, "PVMFOMXAudioDecNode::HandlePortReEnable() new output buffers %d, size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize));
825
826         // assume that the following will fail (it's a special type of buffer allocator). If so - we'd need to
827         // send the FSI at a later time.
828         sendFsi = true;
829         iCompactFSISettingSucceeded = false;
830
831         //Try querying the buffer allocator KVP for output buffer allocation outside of the node
832         PvmiKvp* pkvp = NULL;
833         int NumKvp = 0;
834         PvmiKeyType aKvpIdentifier = (PvmiKeyType)PVMF_SUPPORT_FOR_BUFFER_ALLOCATOR_IN_MIO_KEY;
835         // Check if Fsi configuration need to be sent
836         // Send it only if the MIO supports the buffer allocator
837         if (((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aKvpIdentifier, pkvp, NumKvp) == PVMFSuccess)
838         {
839             //Send the FSI information to media output node here, before setting output
840             //port parameters to the omx component
841             int fsiErrorCode = 0;
842             OsclRefCounterMemFrag FsiMemfrag;
843
844             OSCL_TRY(fsiErrorCode, FsiMemfrag = iFsiFragmentAlloc.get(););
845
846             OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
847                                  (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Failed to allocate memory for  FSI")));
848
849             if (fsiErrorCode == 0)
850             {
851                 channelSampleInfo* pcminfo = (channelSampleInfo*) FsiMemfrag.getMemFragPtr();
852
853                 if (pcminfo != NULL)
854                 {
855                     OSCL_ASSERT(pcminfo != NULL);
856
857                     pcminfo->samplingRate    = iPCMSamplingRate;
858                     pcminfo->desiredChannels = iNumberOfAudioChannels;
859                     pcminfo->bitsPerSample = 16;
860                     pcminfo->num_buffers = iNumOutputBuffers;
861                     pcminfo->buffer_size = iOMXComponentOutputBufferSize;
862
863                     OsclMemAllocator alloc;
864                     int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM) + 1;
865                     PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength);
866
867                     if (NULL == KvpKey)
868                     {
869                         return false;
870                     }
871
872                     oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM, KeyLength);
873                     int32 err;
874
875                     OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey););
876
877                     if (err != OsclErrNone)
878                     {
879                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
880                                         (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Problem to set FSI"));
881                     }
882                     else
883                     {
884                         // FSI setting succeeded. No need to repeat it later
885                         sendFsi = false;
886                         iCompactFSISettingSucceeded = true;
887                     }
888
889                     alloc.deallocate((OsclAny*)(KvpKey));
890                 }
891                 else
892                 {
893                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
894                                     (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Problem allocating Output FSI"));
895                     SetState(EPVMFNodeError);
896                     ReportErrorEvent(PVMFErrNoMemory);
897                     return false; // this is going to make everything go out of scope
898                 }
899             }
900             else
901             {
902                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
903                                 (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Problem allocating Output FSI"));
904                 return false; // this is going to make everything go out of scope
905             }
906
907         }
908         else
909         {
910             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_WARNING,
911                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable Warning- It is OK for this KVP to fail"
912                              "Do NOT attempt to fix the failure in the MIO unless you absolutely want to implement"
913                              "the MIO BUFFER ALLOCATOR - see documentation"));
914
915
916             ReportInfoEvent(PVMFPvmiBufferAllocatorNotAcquired);
917         }
918
919         //Buffer allocator kvp query and allocation has to be done again if we landed into handle port reconfiguration
920
921         PvmiKvp* kvp = NULL;
922         int numKvp = 0;
923         PvmiKeyType aIdentifier = (PvmiKeyType)PVMF_BUFFER_ALLOCATOR_KEY;
924         int32 err, err1;
925         if (ipExternalOutputBufferAllocatorInterface)
926         {
927             ipExternalOutputBufferAllocatorInterface->removeRef();
928             ipExternalOutputBufferAllocatorInterface = NULL;
929         }
930
931         OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aIdentifier, kvp, numKvp););
932
933         if ((err == OsclErrNone) && (NULL != kvp))
934         {
935             ipExternalOutputBufferAllocatorInterface = (PVInterface *)kvp->value.key_specific_value;
936
937             if (ipExternalOutputBufferAllocatorInterface)
938             {
939                 PVInterface* pTempPVInterfacePtr = NULL;
940                 OSCL_TRY(err, ipExternalOutputBufferAllocatorInterface->queryInterface(PVMFFixedSizeBufferAllocUUID, pTempPVInterfacePtr););
941
942                 OSCL_TRY(err1, ((PVMFOMXDecPort*)iOutPort)->releaseParametersSync(kvp, numKvp););
943
944                 if (err1 != OsclErrNone)
945                 {
946                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
947                                     (0, "PVMFOMXAudioDecNode::HandlePortReEnable - Unable to Release Parameters"));
948                 }
949
950                 if ((err == OsclErrNone) && (NULL != pTempPVInterfacePtr))
951                 {
952                     ipFixedSizeBufferAlloc = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, pTempPVInterfacePtr);
953
954                     uint32 iNumBuffers, iBufferSize;
955
956                     iNumBuffers = ipFixedSizeBufferAlloc->getNumBuffers();
957                     iBufferSize = ipFixedSizeBufferAlloc->getBufferSize();
958
959                     if ((iNumBuffers < iParamPort.nBufferCountMin) || (iBufferSize < iOMXComponentOutputBufferSize))
960                     {
961                         ipExternalOutputBufferAllocatorInterface->removeRef();
962                         ipExternalOutputBufferAllocatorInterface = NULL;
963                     }
964                     else
965                     {
966                         iNumOutputBuffers = iNumBuffers;
967                         iOMXComponentOutputBufferSize = iBufferSize;
968                         ReportInfoEvent(PVMFPvmiBufferAlloctorAcquired);
969                     }
970
971                 }
972                 else
973                 {
974                     ipExternalOutputBufferAllocatorInterface->removeRef();
975                     ipExternalOutputBufferAllocatorInterface = NULL;
976                 }
977             }
978         }
979         else
980         {
981             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_WARNING,
982                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable Warning- It is OK for this KVP to fail"
983                              "Do NOT attempt to fix the failure in the MIO unless you absolutely want to implement"
984                              "the MIO BUFFER ALLOCATOR -see documentation"));
985
986             ReportInfoEvent(PVMFPvmiBufferAllocatorNotAcquired);
987         }
988
989         /* Allocate output buffers */
990         if (!CreateOutMemPool(iNumOutputBuffers))
991         {
992
993             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
994                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot allocate output buffers "));
995
996             SetState(EPVMFNodeError);
997             ReportErrorEvent(PVMFErrNoMemory);
998             return PVMFErrNoMemory;
999         }
1000
1001
1002
1003
1004         if (!ProvideBuffersToComponent(iOutBufMemoryPool, // allocator
1005                                        iOutputAllocSize,     // size to allocate from pool (hdr only or hdr+ buffer)
1006                                        iNumOutputBuffers, // number of buffers
1007                                        iOMXComponentOutputBufferSize, // actual buffer size
1008                                        iOutputPortIndex, // port idx
1009                                        iOMXComponentSupportsExternalOutputBufferAlloc, // can component use OMX_UseBuffer
1010                                        false // this is not input
1011                                       ))
1012         {
1013
1014
1015             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1016                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot provide output buffers to component"));
1017
1018             SetState(EPVMFNodeError);
1019             ReportErrorEvent(PVMFErrNoMemory);
1020             return PVMFErrNoMemory;
1021
1022         }
1023
1024         // do not drop output any more, i.e. enable output to be sent downstream
1025         iDoNotSendOutputBuffersDownstreamFlag = false;
1026
1027
1028     }
1029     else
1030     {
1031         // this is input port
1032
1033         // read the alignment again - just in case
1034         iInputBufferAlignment = iParamPort.nBufferAlignment;
1035
1036         iNumInputBuffers = iParamPort.nBufferCountActual;
1037         if (iNumInputBuffers > NUMBER_INPUT_BUFFER)
1038             iNumInputBuffers = NUMBER_INPUT_BUFFER; // make sure number of output buffers is not larger than port queue size
1039
1040         iOMXComponentInputBufferSize = iParamPort.nBufferSize;
1041         // do we need to increase the number of buffers?
1042         if (iNumInputBuffers < iParamPort.nBufferCountMin)
1043             iNumInputBuffers = iParamPort.nBufferCountMin;
1044
1045         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1046                         (0, "PVMFOMXAudioDecNode::HandlePortReEnable() new buffers %d, size %d", iNumInputBuffers, iOMXComponentInputBufferSize));
1047
1048         /* Allocate input buffers */
1049         if (!CreateInputMemPool(iNumInputBuffers))
1050         {
1051             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1052                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot allocate new input buffers to component"));
1053
1054             SetState(EPVMFNodeError);
1055             ReportErrorEvent(PVMFErrNoMemory);
1056             return PVMFErrNoMemory;
1057         }
1058
1059         if (!ProvideBuffersToComponent(iInBufMemoryPool, // allocator
1060                                        iInputAllocSize,  // size to allocate from pool (hdr only or hdr+ buffer)
1061                                        iNumInputBuffers, // number of buffers
1062                                        iOMXComponentInputBufferSize, // actual buffer size
1063                                        iInputPortIndex, // port idx
1064                                        iOMXComponentSupportsExternalInputBufferAlloc, // can component use OMX_UseBuffer
1065                                        true // this is input
1066                                       ))
1067         {
1068
1069
1070             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1071                             (0, "PVMFOMXAudioDecNode::HandlePortReEnable() Port Reconfiguration -> Cannot provide new input buffers to component"));
1072
1073             SetState(EPVMFNodeError);
1074             ReportErrorEvent(PVMFErrNoMemory);
1075             return PVMFErrNoMemory;
1076
1077         }
1078     }
1079
1080     // if the callback that the port was re-enabled has not arrived yet, wait for it
1081     // if it has arrived, it will set the state to either PortReconfig or to ReadyToDecode or InitDecoder (if more init buffers need to be sent)
1082     if (iProcessingState != EPVMFOMXBaseDecNodeProcessingState_PortReconfig &&
1083             iProcessingState != EPVMFOMXBaseDecNodeProcessingState_ReadyToDecode &&
1084             iProcessingState != EPVMFOMXBaseDecNodeProcessingState_InitDecoder)
1085         iProcessingState = EPVMFOMXBaseDecNodeProcessingState_WaitForPortEnable;
1086
1087     return PVMFSuccess; // allow rescheduling of the node
1088 }
1089 ////////////////////////////////////////////////////////////////////////////////
1090 bool PVMFOMXAudioDecNode::NegotiateComponentParameters(OMX_PTR aOutputParameters)
1091 {
1092     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1093                     (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() In"));
1094
1095     OMX_ERRORTYPE Err;
1096     // first get the number of ports and port indices
1097     OMX_PORT_PARAM_TYPE AudioPortParameters;
1098     uint32 NumPorts;
1099     uint32 ii;
1100
1101
1102     pvAudioConfigParserInputs aInputs;
1103     AudioOMXConfigParserOutputs *pOutputParameters;
1104
1105     aInputs.inPtr = (uint8*)((PVMFOMXDecPort*)iInPort)->iTrackConfig;
1106     aInputs.inBytes = (int32)((PVMFOMXDecPort*)iInPort)->iTrackConfigSize;
1107     aInputs.iMimeType = ((PVMFOMXDecPort*)iInPort)->iFormat;
1108     pOutputParameters = (AudioOMXConfigParserOutputs *)aOutputParameters;
1109
1110     // config parser was called prior to calling NegotiateComponentParameters method - the results are available here
1111     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1112                     (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Audio config parser parameters - TrackConfig = %p, TrackConfigSize = %d, mimetype = %s", aInputs.inPtr, aInputs.inBytes, aInputs.iMimeType.getMIMEStrPtr()));
1113
1114
1115     //Initialize the timestamp delta to 0 for all other formats except AAC
1116     iTimestampDeltaForMemFragment = 0;
1117
1118     if (aInputs.iMimeType == PVMF_MIME_WMA)
1119     {
1120         iNumberOfAudioChannels = pOutputParameters->Channels;
1121         iPCMSamplingRate = pOutputParameters->SamplesPerSec;
1122     }
1123     else if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
1124              aInputs.iMimeType == PVMF_MIME_3640 ||
1125              aInputs.iMimeType == PVMF_MIME_LATM ||
1126              aInputs.iMimeType == PVMF_MIME_ADIF ||
1127              aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
1128              aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR)
1129
1130     {
1131         iNumberOfAudioChannels = pOutputParameters->Channels;
1132         iPCMSamplingRate = pOutputParameters->SamplesPerSec;
1133         iSamplesPerFrame = pOutputParameters->SamplesPerFrame;
1134
1135         if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
1136                 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO)
1137         {
1138             // Get the duration of one AAC frame in millisec
1139             MediaClockConverter mcc(iPCMSamplingRate, iSamplesPerFrame);
1140             // calculate the timestamp update in OMX_TICKS (microseconds). This value
1141             // will be added directly to the OMX_TICKS timestamp
1142             iTimestampDeltaForMemFragment = mcc.get_converted_ts(iTimeScale); // this is 1000000 microsecond timescale
1143         }
1144     }
1145
1146
1147     CONFIG_SIZE_AND_VERSION(AudioPortParameters);
1148     // get starting number
1149     Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioInit, &AudioPortParameters);
1150     NumPorts = AudioPortParameters.nPorts; // must be at least 2 of them (in&out)
1151
1152     if (Err != OMX_ErrorNone || NumPorts < 2)
1153     {
1154         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1155                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() There is insuffucient (%d) ports", NumPorts));
1156         return false;
1157     }
1158
1159
1160     // loop through ports starting from the starting index to find index of the first input port
1161     for (ii = AudioPortParameters.nStartPortNumber ; ii < AudioPortParameters.nStartPortNumber + NumPorts; ii++)
1162     {
1163         // get port parameters, and determine if it is input or output
1164         // if there are more than 2 ports, the first one we encounter that has input direction is picked
1165
1166         iParamPort.nSize = sizeof(OMX_PARAM_PORTDEFINITIONTYPE);
1167
1168         //port
1169         iParamPort.nPortIndex = ii;
1170
1171         CONFIG_SIZE_AND_VERSION(iParamPort);
1172
1173         Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1174
1175         if (Err != OMX_ErrorNone)
1176         {
1177             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1178                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with port %d ", ii));
1179
1180             return false;
1181         }
1182
1183         if (iParamPort.eDir == OMX_DirInput)
1184         {
1185             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1186                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Found Input port index %d ", ii));
1187
1188             iInputPortIndex = ii;
1189             break;
1190         }
1191     }
1192     if (ii == AudioPortParameters.nStartPortNumber + NumPorts)
1193     {
1194         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1195                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Cannot find any input port "));
1196         return false;
1197     }
1198
1199
1200     // loop through ports starting from the starting index to find index of the first output port
1201     for (ii = AudioPortParameters.nStartPortNumber ; ii < AudioPortParameters.nStartPortNumber + NumPorts; ii++)
1202     {
1203         // get port parameters, and determine if it is input or output
1204         // if there are more than 2 ports, the first one we encounter that has output direction is picked
1205
1206
1207         //port
1208         iParamPort.nPortIndex = ii;
1209
1210         CONFIG_SIZE_AND_VERSION(iParamPort);
1211
1212         Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1213
1214         if (Err != OMX_ErrorNone)
1215         {
1216             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1217                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with port %d ", ii));
1218
1219             return false;
1220         }
1221
1222         if (iParamPort.eDir == OMX_DirOutput)
1223         {
1224             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1225                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Found Output port index %d ", ii));
1226
1227             iOutputPortIndex = ii;
1228             break;
1229         }
1230     }
1231     if (ii == AudioPortParameters.nStartPortNumber + NumPorts)
1232     {
1233         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1234                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Cannot find any output port "));
1235         return false;
1236     }
1237
1238
1239
1240     // now get input parameters
1241
1242     CONFIG_SIZE_AND_VERSION(iParamPort);
1243
1244     //Input port
1245     iParamPort.nPortIndex = iInputPortIndex;
1246     Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1247     if (Err != OMX_ErrorNone)
1248     {
1249         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1250                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with input port %d ", iInputPortIndex));
1251         return false;
1252     }
1253
1254     // preset the number of input buffers
1255     //iNumInputBuffers = NUMBER_INPUT_BUFFER;
1256     iInputBufferAlignment = iParamPort.nBufferAlignment;
1257     iNumInputBuffers = iParamPort.nBufferCountActual;  // use the value provided by component
1258
1259     // do we need to increase the number of buffers?
1260     if (iNumInputBuffers < iParamPort.nBufferCountMin)
1261         iNumInputBuffers = iParamPort.nBufferCountMin;
1262
1263     iOMXComponentInputBufferSize = iParamPort.nBufferSize;
1264
1265     iParamPort.nBufferCountActual = iNumInputBuffers;
1266
1267     // set the number of actual input buffers
1268     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1269                     (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Inport buffers %d,size %d", iNumInputBuffers, iOMXComponentInputBufferSize));
1270
1271
1272
1273
1274     CONFIG_SIZE_AND_VERSION(iParamPort);
1275     iParamPort.nPortIndex = iInputPortIndex;
1276     iParamPort.format.audio.bFlagErrorConcealment = (OMX_BOOL) iSilenceInsertionFlag;
1277
1278     // finalize setting input port parameters
1279     Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1280     if (Err != OMX_ErrorNone)
1281     {
1282         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1283                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting parameters in input port %d ", iInputPortIndex));
1284         return false;
1285     }
1286
1287
1288     // in case of WMA - config parser decodes config info and produces reliable numchannels and sampling rate
1289     // set these values now to prevent unnecessary port reconfig
1290     // in case of AAC formats - config parser produces a potentially correct numchannels and sampling rate
1291     // however in case of implicit AAC+ signaling, the sampling rate may change and cause a port reconfig
1292     if (aInputs.iMimeType == PVMF_MIME_WMA ||
1293             aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
1294             aInputs.iMimeType == PVMF_MIME_3640 ||
1295             aInputs.iMimeType == PVMF_MIME_LATM ||
1296             aInputs.iMimeType == PVMF_MIME_ADIF ||
1297             aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
1298             aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR)
1299     {
1300         // First get the structure
1301         OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param;
1302         Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params
1303         CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param);
1304
1305         Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param);
1306         if (Err != OMX_ErrorNone)
1307         {
1308             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1309                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating PCM parameters with output port %d ", iOutputPortIndex));
1310             return false;
1311         }
1312
1313         // set the sampling rate obtained from config parser
1314         Audio_Pcm_Param.nSamplingRate = iPCMSamplingRate; // can be set to 0 (if unknown)
1315
1316         // set number of channels obtained from config parser
1317         Audio_Pcm_Param.nChannels = iNumberOfAudioChannels;     // should be 1 or 2
1318
1319         // Now, set the parameters
1320         Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params
1321         CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param);
1322
1323         Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param);
1324         if (Err != OMX_ErrorNone)
1325         {
1326             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1327                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem Setting PCM parameters with output port %d ", iOutputPortIndex));
1328             return false;
1329         }
1330
1331     }
1332
1333
1334     // Codec specific info set/get: SamplingRate, formats etc.
1335     // NOTE: iParamPort is modified in the routine below - it is loaded from the component output port values
1336     // Based on sampling rate - we also determine the desired output buffer size
1337     if (!GetSetCodecSpecificInfo())
1338         return false;
1339
1340     //Port 1 for output port
1341     iParamPort.nPortIndex = iOutputPortIndex;
1342
1343     CONFIG_SIZE_AND_VERSION(iParamPort);
1344
1345     Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1346     if (Err != OMX_ErrorNone)
1347     {
1348         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1349                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with output port %d ", iOutputPortIndex));
1350         return false;
1351     }
1352
1353     // set number of output buffers and the size
1354     iOutputBufferAlignment = iParamPort.nBufferAlignment;
1355
1356     iNumOutputBuffers = iParamPort.nBufferCountActual;
1357
1358     if (iNumOutputBuffers > NUMBER_OUTPUT_BUFFER)
1359         iNumOutputBuffers = NUMBER_OUTPUT_BUFFER; // make sure to limit this number to what the port can hold
1360
1361
1362     if (iNumOutputBuffers < iParamPort.nBufferCountMin)
1363         iNumOutputBuffers = iParamPort.nBufferCountMin;
1364
1365
1366
1367     //Try querying the buffer allocator KVP for output buffer allocation outside of the node
1368
1369     // assume that this is going to fail and set the flags accordingly (so that FSI can be sent later on)
1370     sendFsi = true;
1371     iCompactFSISettingSucceeded = false;
1372
1373     PvmiKvp* pkvp = NULL;
1374     int NumKvp = 0;
1375     PvmiKeyType aKvpIdentifier = (PvmiKeyType)PVMF_SUPPORT_FOR_BUFFER_ALLOCATOR_IN_MIO_KEY;
1376     // Check if Fsi configuration need to be sent
1377     // Send it only if the MIO supports the buffer allocator
1378     if (((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aKvpIdentifier, pkvp, NumKvp) == PVMFSuccess)
1379     {
1380         //Send the FSI information to media output node here, before setting output
1381         //port parameters to the omx component
1382         int fsiErrorCode = 0;
1383
1384         OsclRefCounterMemFrag FsiMemfrag;
1385
1386         OSCL_TRY(fsiErrorCode, FsiMemfrag = iFsiFragmentAlloc.get(););
1387
1388         OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
1389                              (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Failed to allocate memory for  FSI")));
1390
1391         if (fsiErrorCode == 0)
1392         {
1393             channelSampleInfo* pcminfo = (channelSampleInfo*) FsiMemfrag.getMemFragPtr();
1394             if (pcminfo != NULL)
1395             {
1396                 OSCL_ASSERT(pcminfo != NULL);
1397                 pcminfo->samplingRate    = iPCMSamplingRate;
1398                 pcminfo->desiredChannels = iNumberOfAudioChannels;
1399                 pcminfo->bitsPerSample = 16;
1400                 pcminfo->num_buffers = iNumOutputBuffers;
1401                 pcminfo->buffer_size = iOMXComponentOutputBufferSize;
1402
1403                 OsclMemAllocator alloc;
1404                 int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM) + 1;
1405                 PvmiKeyType KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength);
1406
1407                 if (NULL == KvpKey)
1408                 {
1409                     return false;
1410                 }
1411
1412                 oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM, KeyLength);
1413                 int32 err;
1414
1415                 bool success = false;
1416
1417                 OSCL_TRY(err, success = ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey););
1418                 if (err != OsclErrNone || !success)
1419                 {
1420                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1421                                     (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem to set FSI"));
1422                 }
1423                 else
1424                 {
1425                     sendFsi = false;
1426                     iCompactFSISettingSucceeded = true;
1427                 }
1428                 alloc.deallocate((OsclAny*)(KvpKey));
1429
1430
1431             }
1432             else
1433             {
1434                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1435                                 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem allocating Output FSI"));
1436                 SetState(EPVMFNodeError);
1437                 ReportErrorEvent(PVMFErrNoMemory);
1438                 return false; // this is going to make everything go out of scope
1439             }
1440         }
1441         else
1442         {
1443             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1444                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem allocating Output FSI"));
1445             return false; // this is going to make everything go out of scope
1446         }
1447
1448
1449     }
1450     else
1451     {
1452         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_WARNING,
1453                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters Warning- It is OK for this KVP to fail"
1454                          "Do NOT attempt to fix the failure in the MIO unless you absolutely want to implement"
1455                          "the MIO BUFFER ALLOCATOR -see documentation"));
1456
1457         ReportInfoEvent(PVMFPvmiBufferAllocatorNotAcquired);
1458     }
1459     //Try querying the buffer allocator KVP for output buffer allocation outside of the node
1460     PvmiKvp* kvp = NULL;
1461     int numKvp = 0;
1462     PvmiKeyType aIdentifier = (PvmiKeyType)PVMF_BUFFER_ALLOCATOR_KEY;
1463     int32 err, err1;
1464     if (ipExternalOutputBufferAllocatorInterface)
1465     {
1466         ipExternalOutputBufferAllocatorInterface->removeRef();
1467         ipExternalOutputBufferAllocatorInterface = NULL;
1468     }
1469
1470     OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiGetBufferAllocatorSpecificInfoSync(aIdentifier, kvp, numKvp););
1471
1472     if ((err == OsclErrNone) && (NULL != kvp))
1473     {
1474         ipExternalOutputBufferAllocatorInterface = (PVInterface*) kvp->value.key_specific_value;
1475
1476         if (ipExternalOutputBufferAllocatorInterface)
1477         {
1478             PVInterface* pTempPVInterfacePtr = NULL;
1479
1480             OSCL_TRY(err, ipExternalOutputBufferAllocatorInterface->queryInterface(PVMFFixedSizeBufferAllocUUID, pTempPVInterfacePtr););
1481
1482             OSCL_TRY(err1, ((PVMFOMXDecPort*)iOutPort)->releaseParametersSync(kvp, numKvp););
1483             if (err1 != OsclErrNone)
1484             {
1485                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
1486                                 (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Unable to Release Parameters"));
1487             }
1488
1489             if ((err == OsclErrNone) && (NULL != pTempPVInterfacePtr))
1490             {
1491                 ipFixedSizeBufferAlloc = OSCL_STATIC_CAST(PVMFFixedSizeBufferAlloc*, pTempPVInterfacePtr);
1492
1493                 uint32 iNumBuffers, iBufferSize;
1494
1495                 iNumBuffers = ipFixedSizeBufferAlloc->getNumBuffers();
1496                 iBufferSize = ipFixedSizeBufferAlloc->getBufferSize();
1497
1498                 if ((iNumBuffers < iParamPort.nBufferCountMin) || (iBufferSize < iOMXComponentOutputBufferSize))
1499                 {
1500                     ipExternalOutputBufferAllocatorInterface->removeRef();
1501                     ipExternalOutputBufferAllocatorInterface = NULL;
1502                 }
1503                 else
1504                 {
1505                     iNumOutputBuffers = iNumBuffers;
1506                     iOMXComponentOutputBufferSize = iBufferSize;
1507                     ReportInfoEvent(PVMFPvmiBufferAlloctorAcquired);
1508                 }
1509
1510             }
1511             else
1512             {
1513                 ipExternalOutputBufferAllocatorInterface->removeRef();
1514                 ipExternalOutputBufferAllocatorInterface = NULL;
1515
1516             }
1517         }
1518     }
1519     else
1520     {
1521         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_WARNING,
1522                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters Warning- It is OK for this KVP to fail"
1523                          "Do NOT attempt to fix the failure in the MIO unless you absolutely want to implement"
1524                          "the MIO BUFFER ALLOCATOR -see documentation"));
1525
1526         ReportInfoEvent(PVMFPvmiBufferAllocatorNotAcquired);
1527     }
1528
1529     iParamPort.nBufferCountActual = iNumOutputBuffers;
1530
1531     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1532                     (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Outport buffers %d,size %d", iNumOutputBuffers, iOMXComponentOutputBufferSize));
1533
1534     CONFIG_SIZE_AND_VERSION(iParamPort);
1535     iParamPort.nPortIndex = iOutputPortIndex;
1536     // finalize setting output port parameters
1537     Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1538     if (Err != OMX_ErrorNone)
1539     {
1540         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1541                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting parameters in output port %d ", iOutputPortIndex));
1542         return false;
1543     }
1544
1545     //Set input audio format
1546     //This is need it since a single component could handle differents roles
1547
1548     // Init to desire format
1549     PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN;
1550     if (iInPort != NULL)
1551     {
1552         Format = ((PVMFOMXDecPort*)iInPort)->iFormat;
1553     }
1554     if (Format == PVMF_MIME_MPEG4_AUDIO ||
1555             Format == PVMF_MIME_3640 ||
1556             Format == PVMF_MIME_LATM ||
1557             Format == PVMF_MIME_ADIF ||
1558             Format == PVMF_MIME_ASF_MPEG4_AUDIO ||
1559             Format == PVMF_MIME_AAC_SIZEHDR)
1560     {
1561         iOMXAudioCompressionFormat = OMX_AUDIO_CodingAAC;
1562     }
1563     else if (Format == PVMF_MIME_AMR_IF2 ||
1564              Format == PVMF_MIME_AMR_IETF ||
1565              Format == PVMF_MIME_AMR ||
1566              Format == PVMF_MIME_AMRWB_IETF ||
1567              Format == PVMF_MIME_AMRWB)
1568     {
1569         iOMXAudioCompressionFormat = OMX_AUDIO_CodingAMR;
1570     }
1571     else if (Format == PVMF_MIME_MP3)
1572     {
1573         iOMXAudioCompressionFormat = OMX_AUDIO_CodingMP3;
1574     }
1575     else if (Format == PVMF_MIME_WMA)
1576     {
1577         iOMXAudioCompressionFormat = OMX_AUDIO_CodingWMA;
1578     }
1579     else if (Format == PVMF_MIME_REAL_AUDIO)
1580     {
1581         iOMXAudioCompressionFormat = OMX_AUDIO_CodingRA;
1582     }
1583     else
1584     {
1585         // Illegal codec specified.
1586         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1587                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting audio compression format"));
1588         return false;
1589     }
1590
1591
1592     OMX_AUDIO_PARAM_PORTFORMATTYPE AudioPortFormat;
1593     CONFIG_SIZE_AND_VERSION(AudioPortFormat);
1594     AudioPortFormat.nPortIndex = iInputPortIndex;
1595
1596     // Search the proper format index and set it.
1597     // Since we already know that the component has the role we need, search until finding the proper nIndex
1598     // if component does not find the format will return OMX_ErrorNoMore
1599
1600
1601     for (ii = 0; ii < PVOMXAUDIO_MAX_SUPPORTED_FORMAT; ii++)
1602     {
1603         AudioPortFormat.nIndex = ii;
1604         Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPortFormat, &AudioPortFormat);
1605         if (Err != OMX_ErrorNone)
1606         {
1607             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1608                             (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting audio compression format"));
1609             return false;
1610         }
1611         if (iOMXAudioCompressionFormat == AudioPortFormat.eEncoding)
1612         {
1613             break;
1614         }
1615     }
1616
1617     if (ii == PVOMXAUDIO_MAX_SUPPORTED_FORMAT)
1618     {
1619         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1620                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() No audio compression format found"));
1621         return false;
1622
1623     }
1624     // Now set the format to confirm parameters
1625     Err = OMX_SetParameter(iOMXDecoder, OMX_IndexParamAudioPortFormat, &AudioPortFormat);
1626     if (Err != OMX_ErrorNone)
1627     {
1628         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1629                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting audio compression format"));
1630         return false;
1631     }
1632
1633
1634     return true;
1635 }
1636
1637 bool PVMFOMXAudioDecNode::GetSetCodecSpecificInfo()
1638 {
1639
1640     // for AAC, need to let the decoder know about the type of AAC format. Need to get the frame length
1641     // need to get the parameters
1642     OMX_PTR CodecProfilePtr = NULL;
1643     OMX_INDEXTYPE CodecProfileIndx = OMX_IndexAudioStartUnused;
1644     OMX_AUDIO_PARAM_AACPROFILETYPE Audio_Aac_Param;
1645     OMX_AUDIO_PARAM_AMRTYPE Audio_Amr_Param;
1646     OMX_AUDIO_PARAM_MP3TYPE Audio_Mp3_Param;
1647     OMX_AUDIO_PARAM_WMATYPE Audio_Wma_Param;
1648     OMX_AUDIO_PARAM_RATYPE Audio_Ra_Param;
1649     OMX_ERRORTYPE Err = OMX_ErrorNone;
1650     PVMFFormatType Format = PVMF_MIME_FORMAT_UNKNOWN;
1651
1652     // determine the proper index and structure (based on codec type)
1653
1654     if (iInPort != NULL)
1655     {
1656         Format = ((PVMFOMXDecPort*)iInPort)->iFormat;
1657     }
1658     if (Format ==  PVMF_MIME_MPEG4_AUDIO ||
1659             Format == PVMF_MIME_3640 ||
1660             Format == PVMF_MIME_LATM ||
1661             Format == PVMF_MIME_ADIF ||
1662             Format == PVMF_MIME_ASF_MPEG4_AUDIO ||
1663             Format == PVMF_MIME_AAC_SIZEHDR) // for testing
1664     {
1665         // AAC
1666
1667         CodecProfilePtr = (OMX_PTR) & Audio_Aac_Param;
1668         CodecProfileIndx = OMX_IndexParamAudioAac;
1669         Audio_Aac_Param.nPortIndex = iInputPortIndex;
1670
1671         CONFIG_SIZE_AND_VERSION(Audio_Aac_Param);
1672     }
1673     // AMR
1674     else if (Format ==  PVMF_MIME_AMR_IF2 ||
1675              Format == PVMF_MIME_AMR_IETF ||
1676              Format == PVMF_MIME_AMR ||
1677              Format == PVMF_MIME_AMRWB_IETF ||
1678              Format == PVMF_MIME_AMRWB)
1679     {
1680         CodecProfilePtr = (OMX_PTR) & Audio_Amr_Param;
1681         CodecProfileIndx = OMX_IndexParamAudioAmr;
1682         Audio_Amr_Param.nPortIndex = iInputPortIndex;
1683
1684         CONFIG_SIZE_AND_VERSION(Audio_Amr_Param);
1685     }
1686     else if (Format == PVMF_MIME_MP3)
1687     {
1688         CodecProfilePtr = (OMX_PTR) & Audio_Mp3_Param;
1689         CodecProfileIndx = OMX_IndexParamAudioMp3;
1690         Audio_Mp3_Param.nPortIndex = iInputPortIndex;
1691
1692         CONFIG_SIZE_AND_VERSION(Audio_Mp3_Param);
1693     }
1694     else if (Format == PVMF_MIME_WMA)
1695     {
1696         CodecProfilePtr = (OMX_PTR) & Audio_Wma_Param;
1697         CodecProfileIndx = OMX_IndexParamAudioWma;
1698         Audio_Wma_Param.nPortIndex = iInputPortIndex;
1699
1700         CONFIG_SIZE_AND_VERSION(Audio_Wma_Param);
1701     }
1702     else if (Format == PVMF_MIME_REAL_AUDIO)
1703     {
1704         CodecProfilePtr = (OMX_PTR) & Audio_Ra_Param;
1705         CodecProfileIndx = OMX_IndexParamAudioRa;
1706         Audio_Ra_Param.nPortIndex = iInputPortIndex;
1707
1708         CONFIG_SIZE_AND_VERSION(Audio_Ra_Param);
1709     }
1710
1711     // first get parameters:
1712     Err = OMX_GetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr);
1713     if (Err != OMX_ErrorNone)
1714     {
1715         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1716                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem getting codec profile parameter on input port %d ", iInputPortIndex));
1717         return false;
1718     }
1719     // Set the stream format
1720
1721
1722     // AAC FORMATS:
1723     if (Format ==  PVMF_MIME_MPEG4_AUDIO)
1724     {
1725         Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1726     }
1727     else if (Format ==  PVMF_MIME_3640)
1728     {
1729         Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1730     }
1731     else if (Format == PVMF_MIME_LATM)
1732     {
1733         Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4LATM;
1734     }
1735     else if (Format == PVMF_MIME_ADIF)
1736     {
1737         Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatADIF;
1738     }
1739     else if (Format == PVMF_MIME_ASF_MPEG4_AUDIO)
1740     {
1741         Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1742     }
1743     else if (Format == PVMF_MIME_AAC_SIZEHDR) // for testing
1744     {
1745         Audio_Aac_Param.eAACStreamFormat = OMX_AUDIO_AACStreamFormatMP4ADTS;
1746     }
1747     // AMR FORMATS
1748     else if (Format == PVMF_MIME_AMR_IF2)
1749     {
1750         Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatIF2;
1751         Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; // we don't know the bitrate yet, but for init
1752         // purposes, we'll set this to any NarrowBand bitrate
1753         // to indicate NB vs WB
1754     }
1755     // File format
1756     // NB
1757     else if (Format == PVMF_MIME_AMR_IETF)
1758     {
1759         Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1760         Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; // we don't know the bitrate yet, but for init
1761         // purposes, we'll set this to any NarrowBand bitrate
1762         // to indicate NB vs WB
1763     }
1764     // WB
1765     else if (Format == PVMF_MIME_AMRWB_IETF)
1766     {
1767         Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatFSF;
1768         Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0; // we don't know the bitrate yet, but for init
1769         // purposes, we'll set this to any WideBand bitrate
1770         // to indicate NB vs WB
1771     }
1772     // streaming with Table of Contents
1773     else if (Format == PVMF_MIME_AMR)
1774     {
1775         Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatRTPPayload;
1776         Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeNB0; // we don't know the bitrate yet, but for init
1777         // purposes, we'll set this to any WideBand bitrate
1778         // to indicate NB vs WB
1779     }
1780     else if (Format == PVMF_MIME_AMRWB)
1781     {
1782         Audio_Amr_Param.eAMRFrameFormat = OMX_AUDIO_AMRFrameFormatRTPPayload;
1783         Audio_Amr_Param.eAMRBandMode = OMX_AUDIO_AMRBandModeWB0; // we don't know the bitrate yet, but for init
1784         // purposes, we'll set this to any WideBand bitrate
1785         // to indicate NB vs WB
1786     }
1787     else if (Format == PVMF_MIME_MP3)
1788     {
1789         // nothing to do here
1790     }
1791     else if (Format == PVMF_MIME_WMA)
1792     {
1793         Audio_Wma_Param.eFormat = OMX_AUDIO_WMAFormatUnused; // set this initially
1794     }
1795     else if (Format == PVMF_MIME_REAL_AUDIO)
1796     {
1797         Audio_Ra_Param.eFormat = OMX_AUDIO_RA8; // set this initially
1798     }
1799     else
1800     {
1801         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1802                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Unknown format in input port negotiation "));
1803         return false;
1804     }
1805
1806     // set parameters to inform teh component of the stream type
1807     Err = OMX_SetParameter(iOMXDecoder, CodecProfileIndx, CodecProfilePtr);
1808     if (Err != OMX_ErrorNone)
1809     {
1810         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1811                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem setting codec profile parameter on input port %d ", iInputPortIndex));
1812         return false;
1813     }
1814
1815
1816     // read the output frame size
1817     // AAC
1818     if (Format ==  PVMF_MIME_MPEG4_AUDIO ||
1819             Format == PVMF_MIME_3640 ||
1820             Format == PVMF_MIME_LATM ||
1821             Format == PVMF_MIME_ADIF ||
1822             Format == PVMF_MIME_ASF_MPEG4_AUDIO ||
1823             Format == PVMF_MIME_AAC_SIZEHDR) // for testing
1824     {
1825         // AAC frame size is 1024 samples or 2048 samples for AAC-HE
1826         iSamplesPerFrame = Audio_Aac_Param.nFrameLength;
1827     }
1828     // AMR
1829     else if (Format == PVMF_MIME_AMR_IF2 ||
1830              Format == PVMF_MIME_AMR_IETF ||
1831              Format == PVMF_MIME_AMR)
1832     {
1833         // AMR NB has fs=8khz Mono and the frame is 20ms long, i.e. there is 160 samples per frame
1834         iSamplesPerFrame = PVOMXAUDIODEC_AMRNB_SAMPLES_PER_FRAME;
1835     }
1836     else if (Format == PVMF_MIME_AMRWB_IETF ||
1837              Format == PVMF_MIME_AMRWB)
1838     {
1839         // AMR WB has fs=16khz Mono and the frame is 20ms long, i.e. there is 320 samples per frame
1840         iSamplesPerFrame = PVOMXAUDIODEC_AMRWB_SAMPLES_PER_FRAME;
1841     }
1842     else if (Format == PVMF_MIME_MP3)
1843     {
1844         // frame size is either 576 or 1152 samples per frame. However, this information cannot be
1845         // obtained through OMX MP3 Params. Assume that it's 1152
1846         iSamplesPerFrame = PVOMXAUDIODEC_MP3_DEFAULT_SAMPLES_PER_FRAME;
1847     }
1848     else if (Format == PVMF_MIME_WMA)
1849     {
1850         // output frame size is unknown in WMA. However, the PV-WMA decoder can control the number
1851         // of samples it places in an output buffer, so we can create an output buffer of arbitrary size
1852         // and let the decoder control how it is filled
1853         iSamplesPerFrame = 0; // unknown
1854     }
1855     else if (Format == PVMF_MIME_REAL_AUDIO)
1856     {
1857         // samples per frame is unknown in RA as of now, keep it to 0
1858         // and let the decoder control how it is filled
1859         iSamplesPerFrame = 0; // unknown
1860     }
1861
1862
1863     // iSamplesPerFrame depends on the codec.
1864     // for AAC: iSamplesPerFrame = 1024
1865     // for AAC+: iSamplesPerFrame = 2048
1866     // for AMRNB: iSamplesPerFrame = 160
1867     // for AMRWB: iSamplesPerFrame = 320
1868     // for MP3:   iSamplesPerFrame = unknown, but either 1152 or 576 (we pick 1152 as default)
1869     // for WMA:    unknown (iSamplesPerFrame is set to 0)
1870     // for RA:     unknown (iSamplesPerFrame is set to 0)
1871
1872     // GET the output buffer params and sizes
1873     OMX_AUDIO_PARAM_PCMMODETYPE Audio_Pcm_Param;
1874     Audio_Pcm_Param.nPortIndex = iOutputPortIndex; // we're looking for output port params
1875
1876     CONFIG_SIZE_AND_VERSION(Audio_Pcm_Param);
1877
1878
1879     Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamAudioPcm, &Audio_Pcm_Param);
1880     if (Err != OMX_ErrorNone)
1881     {
1882         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1883                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating PCM parameters with output port %d ", iOutputPortIndex));
1884         return false;
1885     }
1886
1887
1888     // these are some initial default values that may change
1889     iPCMSamplingRate = Audio_Pcm_Param.nSamplingRate; // can be set to 0 (if unknown)
1890
1891     if (iPCMSamplingRate == 0) // use default sampling rate (i.e. 48000)
1892         iPCMSamplingRate = PVOMXAUDIODEC_DEFAULT_SAMPLINGRATE;
1893
1894     iNumberOfAudioChannels = Audio_Pcm_Param.nChannels;     // should be 1 or 2
1895     if (iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2)
1896         return false;
1897
1898
1899     if ((iSamplesPerFrame != 0) && ((iSamplesPerFrame * 1000) > iPCMSamplingRate))
1900         // if this iSamplesPerFrame is known and is large enough to ensure that the iMilliSecPerFrame calculation
1901         // below won't be set to 0.
1902     {
1903         // CALCULATE NumBytes per frame, Msec per frame, etc.
1904
1905         iNumBytesPerFrame = 2 * iSamplesPerFrame * iNumberOfAudioChannels;
1906         iMilliSecPerFrame = (iSamplesPerFrame * 1000) / iPCMSamplingRate;
1907         // Determine the size of each PCM output buffer. Size would be big enough to hold certain time amount of PCM data
1908         uint32 numframes = iOutputBufferPCMDuration / iMilliSecPerFrame;
1909
1910         if (iOutputBufferPCMDuration % iMilliSecPerFrame)
1911         {
1912             // If there is a remainder, include one more frame
1913             ++numframes;
1914         }
1915         // set the output buffer size accordingly:
1916         iOMXComponentOutputBufferSize = numframes * iNumBytesPerFrame;
1917     }
1918     else
1919         iOMXComponentOutputBufferSize = (2 * iNumberOfAudioChannels * iOutputBufferPCMDuration * iPCMSamplingRate) / 1000; // assuming 16 bits per sample
1920
1921     if (iBOCReceived)
1922         CalculateBOCParameters();
1923
1924     if (iEOCReceived)
1925         CalculateEOCParameters();
1926
1927     //Port 1 for output port
1928     iParamPort.nPortIndex = iOutputPortIndex;
1929     CONFIG_SIZE_AND_VERSION(iParamPort);
1930     Err = OMX_GetParameter(iOMXDecoder, OMX_IndexParamPortDefinition, &iParamPort);
1931     if (Err != OMX_ErrorNone)
1932     {
1933         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1934                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters() Problem negotiating with output port %d ", iOutputPortIndex));
1935         return false;
1936     }
1937
1938     if (iOMXComponentOutputBufferSize < iParamPort.nBufferSize)
1939     {
1940         // the OMX spec says that nBuffersize is a read only field, but the client is allowed to allocate
1941         // a buffer size larger than nBufferSize.
1942         iOMXComponentOutputBufferSize = iParamPort.nBufferSize;
1943     }
1944
1945     return true;
1946
1947 }
1948
1949 /////////////////////////////////////////////////////////////////////////////
1950 PVMFStatus PVMFOMXAudioDecNode::InitDecoder(PVMFSharedMediaDataPtr& DataIn)
1951 {
1952
1953     OsclRefCounterMemFrag DataFrag;
1954     OsclRefCounterMemFrag refCtrMemFragOut;
1955     uint8* initbuffer = NULL;
1956     uint32 initbufsize = 0;
1957     PVMFStatus status = PVMFSuccess;
1958
1959     // NOTE: the component may not start decoding without providing the Output buffer to it,
1960     //      here, we're sending input/config buffers.
1961     //      Then, we'll go to ReadyToDecode state and send output as well
1962
1963     if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM)
1964     {
1965         // must have the LATM config buffer and size already present
1966         if (iLATMConfigBuffer != NULL)
1967         {
1968             initbuffer = iLATMConfigBuffer;
1969             initbufsize = iLATMConfigBufferSize;
1970         }
1971         else
1972         {
1973             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
1974                             (0, "PVMFOMXAudioDecNode::InitDecoder() Error - LATM config buffer not present"));
1975             return PVMFFailure;
1976         }
1977     }
1978     else if (((PVMFOMXDecPort*)iInPort)->iFormat ==  PVMF_MIME_MPEG4_AUDIO ||
1979              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640 ||
1980              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF ||
1981              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO ||
1982              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AAC_SIZEHDR) // for testing
1983     {
1984         // get format specific info and send it as config data:
1985         DataIn->getFormatSpecificInfo(DataFrag);
1986         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
1987                         (0, "PVMFOMXAudioDecNode::InitDecoder() VOL header (Size=%d)", DataFrag.getMemFragSize()));
1988
1989         //get pointer to the data fragment
1990         initbuffer = (uint8 *) DataFrag.getMemFragPtr();
1991         initbufsize = (int32) DataFrag.getMemFragSize();
1992
1993         // in case of ASF_MPEG4 audio need to create aac config header
1994         if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO)
1995         {
1996
1997
1998             if (!CreateAACConfigDataFromASF(initbuffer, initbufsize, &iAACConfigData[0], iAACConfigDataLength))
1999             {
2000                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
2001                                 (0, "PVMFOMXAudioDecNode::InitDecoder() Error in creating AAC Codec Config data"));
2002
2003                 return PVMFFailure;
2004             }
2005
2006             initbuffer  = &iAACConfigData[0];
2007             initbufsize = iAACConfigDataLength;
2008         }
2009
2010
2011     }           // in some cases, initbufsize may be 0, and initbuf= NULL. Config is done after 1st frame of data
2012     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2 ||
2013              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF ||
2014              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR ||
2015              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF ||
2016              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB ||
2017              ((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3)
2018     {
2019         initbuffer = NULL; // no special config header. Need to decode 1 frame
2020         initbufsize = 0;
2021     }
2022
2023     else if ((((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) ||
2024              (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_REAL_AUDIO))
2025     {
2026         // in case of WMA, get config parameters from the port
2027         initbuffer = ((PVMFOMXDecPort*)iInPort)->getTrackConfig();
2028         initbufsize = (int32)((PVMFOMXDecPort*)iInPort)->getTrackConfigSize();
2029
2030         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2031                         (0, "PVMFOMXAudioDecNode::InitDecoder() for WMA Decoder. Initialization data Size %d.", initbufsize));
2032     }
2033
2034     if (initbufsize > 0)
2035     {
2036
2037
2038         status = SendConfigBufferToOMXComponent(initbuffer, initbufsize);
2039         if (status != PVMFSuccess)
2040         {
2041             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
2042                             (0, "PVMFOMXAudioDecNode::InitDecoder() Error in processing config buffer"));
2043             iIsThereMoreConfigDataToBeSent = true; // this means that we may not have buffers available to send,
2044             return status;
2045         }
2046
2047         // set the flag requiring config data processing by the component
2048         iIsConfigDataProcessingCompletionNeeded = true;
2049         iConfigDataBuffersOutstanding++;
2050         iIsThereMoreConfigDataToBeSent = false;
2051     }
2052     else
2053     {
2054         iIsThereMoreConfigDataToBeSent = false;
2055     }
2056
2057     return PVMFSuccess;
2058 }
2059
2060
2061 /////////////////////////////////////////////////////////////////////////////
2062 ////////////////////// CALLBACK PROCESSING FOR FILL BUFFER DONE - output buffer is ready
2063 /////////////////////////////////////////////////////////////////////////////
2064 OMX_ERRORTYPE PVMFOMXAudioDecNode::FillBufferDoneProcessing(OMX_OUT OMX_HANDLETYPE aComponent,
2065         OMX_OUT OMX_PTR aAppData,
2066         OMX_OUT OMX_BUFFERHEADERTYPE* aBuffer)
2067 {
2068     OSCL_UNUSED_ARG(aComponent);
2069     OSCL_UNUSED_ARG(aAppData);
2070
2071     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2072                     (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: In"));
2073
2074     OSCL_ASSERT((void*) aComponent == (void*) iOMXDecoder); // component should match the component
2075     OSCL_ASSERT(aAppData == (OMX_PTR)(this));       // AppData should represent this node ptr
2076
2077     // first, get the buffer "context", i.e. pointer to application private data that contains the
2078     // address of the mempool buffer (so that it can be released)
2079     OutputBufCtrlStruct *pContext = (OutputBufCtrlStruct*) aBuffer->pAppPrivate;
2080
2081     // check for EOS flag
2082     if ((aBuffer->nFlags & OMX_BUFFERFLAG_EOS))
2083     {
2084         // EOS received - enable sending EOS msg
2085         iIsEOSReceivedFromComponent = true;
2086
2087         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2088                         (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Output buffer has EOS set"));
2089     }
2090
2091     if (iCountSamplesInBuffer)
2092     {
2093         CountSamplesInBuffer(aBuffer);
2094     }
2095
2096     // check for BOC.
2097     if (iBOCReceived)
2098     {
2099         HandleBOCProcessing(aBuffer);
2100     }
2101
2102     // check for EOC.
2103     if (iEOCReceived)
2104     {
2105         HandleEOCProcessing(aBuffer);
2106     }
2107
2108     // if a buffer is empty, or if it should not be sent downstream (say, due to state change)
2109     // release the buffer back to the pool
2110     if ((aBuffer->nFilledLen == 0) || (iDoNotSendOutputBuffersDownstreamFlag == true))
2111     {
2112         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2113                         (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Release output buffer %x pointing to buffer %x back to mempool - buffer empty or not to be sent downstream", pContext, pContext->pMemPoolEntry));
2114
2115         iOutBufMemoryPool->deallocate(pContext->pMemPoolEntry);
2116     }
2117     else
2118     {
2119
2120         // get pointer to actual buffer data
2121         uint8 *pBufdata = ((uint8*) aBuffer->pBuffer);
2122         // move the data pointer based on offset info
2123         pBufdata += aBuffer->nOffset;
2124
2125         iOutTimeStamp = ConvertOMXTicksIntoTimestamp(aBuffer->nTimeStamp);
2126
2127         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2128                         (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Output frame %d with timestamp %d received", iFrameCounter++, iOutTimeStamp));
2129
2130
2131         ipPrivateData = (OsclAny *) aBuffer->pPlatformPrivate; // record the pointer
2132
2133         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2134                         (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Wrapping buffer %x of size %d", pBufdata, aBuffer->nFilledLen));
2135         // wrap the buffer into the MediaDataImpl wrapper, and queue it for sending downstream
2136         // wrapping will create a refcounter. When refcounter goes to 0 i.e. when media data
2137         // is released in downstream components, the custom deallocator will automatically release the buffer back to the
2138         //  mempool. To do that, the deallocator needs to have info about Context
2139         // NOTE: we had to wait until now to wrap the buffer data because we only know
2140         //          now where the actual data is located (based on buffer offset)
2141         OsclSharedPtr<PVMFMediaDataImpl> MediaDataOut = WrapOutputBuffer(pBufdata, (uint32)(aBuffer->nFilledLen), pContext->pMemPoolEntry);
2142
2143         // if you can't get the MediaDataOut, release the buffer back to the pool
2144         if (MediaDataOut.GetRep() == NULL)
2145         {
2146             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2147                             (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Problem wrapping buffer %x of size %d - releasing the buffer", pBufdata, aBuffer->nFilledLen));
2148
2149             iOutBufMemoryPool->deallocate(pContext->pMemPoolEntry);
2150         }
2151         else
2152         {
2153
2154             // if there's a problem queuing output buffer, MediaDataOut will expire at end of scope and
2155             // release buffer back to the pool, (this should not be the case)
2156             if (QueueOutputBuffer(MediaDataOut, aBuffer->nFilledLen))
2157             {
2158                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2159                                 (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Buffer %x of size %d queued - reschedule the node to send out", pBufdata, aBuffer->nFilledLen));
2160
2161                 // if queing went OK,
2162                 // re-schedule the node so that outgoing queue can be emptied (unless the outgoing port is busy)
2163                 if ((iOutPort) && !(iOutPort->IsConnectedPortBusy()))
2164                     RunIfNotReady();
2165             }
2166             else
2167             {
2168                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2169                                 (0, "PVMFOMXAudioDecNode::FillBufferDoneProcessing: Problem queing buffer %x of size %d - releasing the buffer", pBufdata, aBuffer->nFilledLen));
2170             }
2171
2172
2173         }
2174
2175     }
2176     // the OMX spec says that no error is to be returned
2177     return OMX_ErrorNone;
2178
2179 }
2180
2181 ////////////////////////////////////////////////////////////////////////////////////////////////
2182 ///////////////////////////// Put output buffer in outgoing queue //////////////////////////////
2183 ////////////////////////////////////////////////////////////////////////////////////////////////
2184 bool PVMFOMXAudioDecNode::QueueOutputBuffer(OsclSharedPtr<PVMFMediaDataImpl> &mediadataimplout, uint32 aDataLen)
2185 {
2186
2187     bool status = true;
2188     PVMFSharedMediaDataPtr mediaDataOut;
2189     int32 leavecode = OsclErrNone;
2190
2191     // NOTE: ASSUMPTION IS THAT OUTGOING QUEUE IS BIG ENOUGH TO QUEUE ALL THE OUTPUT BUFFERS
2192     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2193                     (0, "PVMFOMXAudioDecNode::QueueOutputFrame: In"));
2194
2195     if (!iOutPort)
2196     {
2197         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2198                         (0, "PVMFOMXAudioDecNode::QueueOutputFrame() Output Port doesn't exist!!!!!!!!!!"));
2199         return false;
2200     }
2201     // First check if we can put outgoing msg. into the queue
2202     if (iOutPort->IsOutgoingQueueBusy())
2203     {
2204         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2205                         (0, "PVMFOMXAudioDecNode::QueueOutputFrame() OutgoingQueue is busy"));
2206         return false;
2207     }
2208
2209     OSCL_TRY(leavecode,
2210              mediaDataOut = PVMFMediaData::createMediaData(mediadataimplout, iOutputMediaDataMemPool););
2211     if (OsclErrNone == leavecode)
2212     {
2213         // Update the filled length of the fragment
2214         mediaDataOut->setMediaFragFilledLen(0, aDataLen);
2215
2216         // Set timestamp
2217         mediaDataOut->setTimestamp(iOutTimeStamp);
2218
2219         // Set Duration
2220         // Duration = (OutputBufferSize * 1000)/(SamplingRate * NumChannels * BitsPerSample/8)
2221         uint32 duration = (iOMXComponentOutputBufferSize * 1000) / (iPCMSamplingRate * iNumberOfAudioChannels * 16 / 8);
2222         mediaDataOut->setDuration(duration);
2223
2224         // Get the markerinfo and set the Duration Bit
2225         uint32 markerInfo = mediaDataOut->getMarkerInfo();
2226         markerInfo |= PVMF_MEDIA_DATA_MARKER_INFO_DURATION_AVAILABLE_BIT;
2227         mediaDataOut->setMarkerInfo(markerInfo);
2228
2229         // Set sequence number
2230         mediaDataOut->setSeqNum(iSeqNum++);
2231         // set stream id
2232         mediaDataOut->setStreamID(iStreamID);
2233
2234         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iDataPathLogger, PVLOGMSG_INFO, (0, ":PVMFOMXAudioDecNode::QueueOutputFrame(): - SeqNum=%d, TS=%d", iSeqNum, iOutTimeStamp));
2235         int fsiErrorCode = 0;
2236
2237         // Check if Fsi configuration need to be sent
2238         if (sendFsi && !iCompactFSISettingSucceeded)
2239         {
2240
2241             OsclRefCounterMemFrag FsiMemfrag;
2242
2243             OSCL_TRY(fsiErrorCode, FsiMemfrag = iFsiFragmentAlloc.get(););
2244
2245             OSCL_FIRST_CATCH_ANY(fsiErrorCode, PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
2246                                  (0, "PVMFOMXAudioDecNode::RemoveOutputFrame() Failed to allocate memory for  FSI")));
2247
2248             if (fsiErrorCode == 0)
2249             {
2250
2251                 channelSampleInfo* pcminfo = (channelSampleInfo*) FsiMemfrag.getMemFragPtr();
2252                 if (pcminfo != NULL)
2253                 {
2254                     OSCL_ASSERT(pcminfo != NULL);
2255
2256                     pcminfo->samplingRate    = iPCMSamplingRate;
2257                     pcminfo->desiredChannels = iNumberOfAudioChannels;
2258                     pcminfo->bitsPerSample = 16;
2259                     pcminfo->num_buffers = 0;
2260                     pcminfo->buffer_size = 0;
2261
2262                     mediaDataOut->setFormatSpecificInfo(FsiMemfrag);
2263
2264
2265                     OsclMemAllocator alloc;
2266                     int32 KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM) + 1;
2267
2268                     PvmiKeyType KvpKey = NULL;
2269                     AllocatePvmiKey(&KvpKey, &alloc, KeyLength);
2270
2271                     if (NULL == KvpKey)
2272                     {
2273                         SetState(EPVMFNodeError);
2274                         ReportErrorEvent(PVMFErrNoMemory);
2275                         return false;
2276                     }
2277
2278                     oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY_PCM, KeyLength);
2279                     int32 err;
2280
2281                     OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey););
2282                     if (err != OsclErrNone)
2283                     {
2284                         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2285                                         (0, "PVMFOMXAudioDecNode::NegotiateComponentParameters - Problem to set FSI_PCM key, will try to send ordinary FSI"));
2286
2287                         alloc.deallocate((OsclAny*)(KvpKey));
2288
2289
2290                         // try to send the ordinary FSI
2291                         KeyLength = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY) + 1;
2292                         KvpKey = (PvmiKeyType)alloc.ALLOCATE(KeyLength);
2293                         if (NULL == KvpKey)
2294                         {
2295                             SetState(EPVMFNodeError);
2296                             ReportErrorEvent(PVMFErrNoMemory);
2297                             return false;
2298                         }
2299
2300                         oscl_strncpy(KvpKey, PVMF_FORMAT_SPECIFIC_INFO_KEY, KeyLength);
2301
2302
2303                         OSCL_TRY(err, ((PVMFOMXDecPort*)iOutPort)->pvmiSetPortFormatSpecificInfoSync(FsiMemfrag, KvpKey););
2304                         if (err != OsclErrNone)
2305                         {
2306                             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2307                                             (0, "PVMFOMXAudioDecNode::QueueOutputFrame - Problem to set ordinary FSI as well"));
2308
2309                             alloc.deallocate((OsclAny*)(KvpKey));
2310
2311                             SetState(EPVMFNodeError);
2312                             ReportErrorEvent(PVMFErrNoMemory);
2313                             return false; // this is going to make everything go out of scope
2314                         }
2315                     }
2316
2317                     alloc.deallocate((OsclAny*)(KvpKey));
2318                 }
2319                 else
2320                 {
2321                     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2322                                     (0, "PVMFOMXAudioDecNode::QueueOutputFrame - Problem allocating Output FSI"));
2323                     SetState(EPVMFNodeError);
2324                     ReportErrorEvent(PVMFErrNoMemory);
2325                     return false; // this is going to make everything go out of scope
2326                 }
2327             }
2328             else
2329             {
2330                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
2331                                 (0, "PVMFOMXAudioDecNode::QueueOutputFrame - Problem allocating Output FSI"));
2332                 return false; // this is going to make everything go out of scope
2333             }
2334
2335             // Reset the flag
2336             sendFsi = false;
2337         }
2338
2339         if (fsiErrorCode == 0)
2340         {
2341             // Send frame to downstream node
2342             PVMFSharedMediaMsgPtr mediaMsgOut;
2343             convertToPVMFMediaMsg(mediaMsgOut, mediaDataOut);
2344
2345             if (iOutPort && (iOutPort->QueueOutgoingMsg(mediaMsgOut) == PVMFSuccess))
2346             {
2347                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_DEBUG,
2348                                 (0, "PVMFOMXAudioDecNode::QueueOutputFrame(): Queued frame OK "));
2349
2350             }
2351             else
2352             {
2353                 // we should not get here because we always check for whether queue is busy or not
2354                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
2355                                 (0, "PVMFOMXAudioDecNode::QueueOutputFrame(): Send frame failed"));
2356                 return false;
2357             }
2358         }
2359
2360     }//end of if (OsclErrNone == leavecode)
2361     else
2362     {
2363         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
2364                         (0, "PVMFOMXAudioDecNode::QueueOutputFrame() call PVMFMediaData::createMediaData is failed"));
2365         return false;
2366     }
2367
2368     return status;
2369 }
2370
2371 /////////////////////////////////////////////////////////////////////////////
2372 PVMFStatus PVMFOMXAudioDecNode::DoRequestPort(PVMFPortInterface*& aPort)
2373 {
2374     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2375                     (0, "PVMFOMXAudioDecNode::DoRequestPort() In"));
2376     //This node supports port request from any state
2377
2378     //retrieve port tag.
2379     int32 tag;
2380     OSCL_String* portconfig;
2381
2382     iCurrentCommand.PVMFNodeCommandBase::Parse(tag, portconfig);
2383
2384     int32 leavecode = OsclErrNone;
2385     //validate the tag...
2386     switch (tag)
2387     {
2388         case PVMF_OMX_DEC_NODE_PORT_TYPE_INPUT:
2389             if (iInPort)
2390             {
2391                 return PVMFFailure;
2392                 break;
2393             }
2394             OSCL_TRY(leavecode, iInPort = OSCL_NEW(PVMFOMXDecPort, ((int32)tag, this, (OMX_STRING)PVMF_OMX_AUDIO_DEC_INPUT_PORT_NAME)););
2395             if (leavecode || iInPort == NULL)
2396             {
2397                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
2398                                 (0, "PVMFOMXAudioDecNode::DoRequestPort: Error - Input port instantiation failed"));
2399                 return PVMFErrArgument;
2400             }
2401             aPort = iInPort;
2402             break;
2403
2404         case PVMF_OMX_DEC_NODE_PORT_TYPE_OUTPUT:
2405             if (iOutPort)
2406             {
2407                 return PVMFFailure;
2408                 break;
2409             }
2410             OSCL_TRY(leavecode, iOutPort = OSCL_NEW(PVMFOMXDecPort, ((int32)tag, this, (OMX_STRING)PVMF_OMX_AUDIO_DEC_OUTPUT_PORT_NAME)));
2411             if (leavecode || iOutPort == NULL)
2412             {
2413                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
2414                                 (0, "PVMFOMXAudioDecNode::DoRequestPort: Error - Output port instantiation failed"));
2415                 return PVMFErrArgument;
2416             }
2417             aPort = iOutPort;
2418             break;
2419
2420         default:
2421             //bad port tag
2422             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_ERR,
2423                             (0, "PVMFOMXAudioDecNode::DoRequestPort: Error - Invalid port tag"));
2424             return PVMFErrArgument;
2425     }
2426     return PVMFSuccess;
2427 }
2428
2429
2430 /////////////////////////////////////////////////////////////////////////////
2431 PVMFStatus PVMFOMXAudioDecNode::DoGetNodeMetadataKey()
2432 {
2433     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
2434                     (0, "PVMFOMXAudioDecNode::DoGetNodeMetadataKey() In"));
2435
2436     PVMFMetadataList* keylistptr = NULL;
2437     uint32 starting_index;
2438     int32 max_entries;
2439     char* query_key;
2440
2441     iCurrentCommand.PVMFNodeCommand::Parse(keylistptr, starting_index, max_entries, query_key);
2442
2443     // Check parameters
2444     if (keylistptr == NULL)
2445     {
2446         // The list pointer is invalid
2447         return PVMFErrArgument;
2448     }
2449
2450     // Update the available metadata keys
2451     iAvailableMetadataKeys.clear();
2452     int32 leavecode = OsclErrNone;
2453     leavecode = PushKVPKey(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY, iAvailableMetadataKeys);
2454     if (OsclErrNone != leavecode)
2455     {
2456         return PVMFErrNoMemory;
2457     }
2458
2459     if (iNumberOfAudioChannels > 0)
2460     {
2461         leavecode = OsclErrNone;
2462         leavecode = PushKVPKey(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY, iAvailableMetadataKeys);
2463         if (OsclErrNone != leavecode)
2464         {
2465             return PVMFErrNoMemory;
2466         }
2467     }
2468
2469     if (iPCMSamplingRate > 0)
2470     {
2471         leavecode = OsclErrNone;
2472         leavecode = PushKVPKey(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY, iAvailableMetadataKeys);
2473         if (OsclErrNone != leavecode)
2474         {
2475             return PVMFErrNoMemory;
2476         }
2477     }
2478
2479     if ((starting_index > (iAvailableMetadataKeys.size() - 1)) || max_entries == 0)
2480     {
2481         // Invalid starting index and/or max entries
2482         return PVMFErrArgument;
2483     }
2484
2485     // Copy the requested keys
2486     uint32 num_entries = 0;
2487     int32 num_added = 0;
2488     for (uint32 lcv = 0; lcv < iAvailableMetadataKeys.size(); lcv++)
2489     {
2490         if (query_key == NULL)
2491         {
2492             // No query key so this key is counted
2493             ++num_entries;
2494             if (num_entries > starting_index)
2495             {
2496                 // Past the starting index so copy the key
2497                 leavecode = OsclErrNone;
2498                 leavecode = PushKVPKey(iAvailableMetadataKeys[lcv], keylistptr);
2499                 if (OsclErrNone != leavecode)
2500                 {
2501                     return PVMFErrNoMemory;
2502                 }
2503
2504                 num_added++;
2505             }
2506         }
2507         else
2508         {
2509             // Check if the key matche the query key
2510             if (pv_mime_strcmp(iAvailableMetadataKeys[lcv].get_cstr(), query_key) >= 0)
2511             {
2512                 // This key is counted
2513                 ++num_entries;
2514                 if (num_entries > starting_index)
2515                 {
2516                     // Past the starting index so copy the key
2517                     leavecode = OsclErrNone;
2518                     leavecode = PushKVPKey(iAvailableMetadataKeys[lcv], keylistptr);
2519                     if (OsclErrNone != leavecode)
2520                     {
2521                         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoGetNodeMetadataKey() Memory allocation failure when copying metadata key"));
2522                         return PVMFErrNoMemory;
2523                     }
2524
2525                     num_added++;
2526                 }
2527             }
2528         }
2529
2530         // Check if max number of entries have been copied
2531         if (max_entries > 0 && num_added >= max_entries)
2532         {
2533             break;
2534         }
2535     }
2536
2537     return PVMFSuccess;
2538 }
2539
2540 /////////////////////////////////////////////////////////////////////////////
2541 PVMFStatus PVMFOMXAudioDecNode::DoGetNodeMetadataValue()
2542 {
2543     PVMFMetadataList* keylistptr = NULL;
2544     Oscl_Vector<PvmiKvp, OsclMemAllocator>* valuelistptr = NULL;
2545     uint32 starting_index;
2546     int32 max_entries;
2547
2548     iCurrentCommand.PVMFNodeCommand::Parse(keylistptr, valuelistptr, starting_index, max_entries);
2549
2550     // Check the parameters
2551     if (keylistptr == NULL || valuelistptr == NULL)
2552     {
2553         return PVMFErrArgument;
2554     }
2555
2556     uint32 numkeys = keylistptr->size();
2557
2558     if (starting_index > (numkeys - 1) || numkeys <= 0 || max_entries == 0)
2559     {
2560         // Don't do anything
2561         return PVMFErrArgument;
2562     }
2563
2564     uint32 numvalentries = 0;
2565     int32 numentriesadded = 0;
2566     for (uint32 lcv = 0; lcv < numkeys; lcv++)
2567     {
2568         int32 leavecode = OsclErrNone;
2569         int32 leavecode1 = OsclErrNone;
2570         PvmiKvp KeyVal;
2571         KeyVal.key = NULL;
2572         uint32 KeyLen = 0;
2573
2574         if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) == 0))
2575         {
2576             // PCM output channels
2577             if (iNumberOfAudioChannels > 0)
2578             {
2579                 // Increment the counter for the number of values found so far
2580                 ++numvalentries;
2581
2582                 // Create a value entry if past the starting index
2583                 if (numvalentries > starting_index)
2584                 {
2585                     KeyLen = oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) + 1; // for "codec-info/audio/channels;"
2586                     KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
2587                     KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
2588
2589                     // Allocate memory for the string
2590                     leavecode = OsclErrNone;
2591                     KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
2592                     if (OsclErrNone == leavecode)
2593                     {
2594                         // Copy the key string
2595                         oscl_strncpy(KeyVal.key, PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY, oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) + 1);
2596                         oscl_strncat(KeyVal.key, PVOMXAUDIODECMETADATA_SEMICOLON, oscl_strlen(PVOMXAUDIODECMETADATA_SEMICOLON));
2597                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
2598                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
2599                         KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
2600                         // Copy the value
2601                         KeyVal.value.uint32_value = iNumberOfAudioChannels;
2602                         // Set the length and capacity
2603                         KeyVal.length = 1;
2604                         KeyVal.capacity = 1;
2605                     }
2606                     else
2607                     {
2608                         // Memory allocation failed
2609                         KeyVal.key = NULL;
2610                         break;
2611                     }
2612                 }
2613             }
2614         }
2615         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) == 0) &&
2616                  (iPCMSamplingRate > 0))
2617         {
2618             // PCM output sampling rate
2619             // Increment the counter for the number of values found so far
2620             ++numvalentries;
2621
2622             // Create a value entry if past the starting index
2623             if (numvalentries > starting_index)
2624             {
2625                 KeyLen = oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) + 1; // for "codec-info/audio/sample-rate;"
2626                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
2627                 KeyLen += oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR) + 1; // for "uint32" and NULL terminator
2628
2629                 // Allocate memory for the string
2630                 leavecode = OsclErrNone;
2631                 KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
2632                 if (OsclErrNone == leavecode)
2633                 {
2634                     // Copy the key string
2635                     oscl_strncpy(KeyVal.key, PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY, oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) + 1);
2636                     oscl_strncat(KeyVal.key, PVOMXAUDIODECMETADATA_SEMICOLON, oscl_strlen(PVOMXAUDIODECMETADATA_SEMICOLON));
2637                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
2638                     oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_UINT32_STRING_CONSTCHAR));
2639                     KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
2640                     // Copy the value
2641                     KeyVal.value.uint32_value = iPCMSamplingRate;
2642                     // Set the length and capacity
2643                     KeyVal.length = 1;
2644                     KeyVal.capacity = 1;
2645                 }
2646                 else
2647                 {
2648                     // Memory allocation failed
2649                     KeyVal.key = NULL;
2650                     break;
2651                 }
2652             }
2653         }
2654         else if ((oscl_strcmp((*keylistptr)[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) == 0) &&
2655                  iInPort != NULL)
2656         {
2657             // Format
2658             if ((((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) ||
2659                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO) ||
2660                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640) ||
2661                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF) ||
2662                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO) ||
2663                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AAC_SIZEHDR) ||
2664                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2) ||
2665                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF) ||
2666                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) ||
2667                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF) ||
2668                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) ||
2669                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) ||
2670                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) ||
2671                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_REAL_AUDIO)
2672
2673                )
2674             {
2675                 // Increment the counter for the number of values found so far
2676                 ++numvalentries;
2677
2678                 // Create a value entry if past the starting index
2679                 if (numvalentries > starting_index)
2680                 {
2681                     KeyLen = oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) + 1; // for "codec-info/audio/format;"
2682                     KeyLen += oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR); // for "valtype="
2683                     KeyLen += oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR) + 1; // for "char*" and NULL terminator
2684
2685                     uint32 valuelen = 0;
2686                     if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM)
2687                     {
2688                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_LATM)) + 1; // Value string plus one for NULL terminator
2689                     }
2690                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO)
2691                     {
2692                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_MPEG4_AUDIO)) + 1; // Value string plus one for NULL terminator
2693                     }
2694                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640)
2695                     {
2696                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_3640)) + 1; // Value string plus one for NULL terminator
2697                     }
2698                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF)
2699                     {
2700                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_ADIF)) + 1;
2701                     }
2702                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO)
2703                     {
2704                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_ASF_MPEG4_AUDIO)) + 1;
2705                     }
2706                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2)
2707                     {
2708                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMR_IF2)) + 1;
2709                     }
2710                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF)
2711                     {
2712                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMR_IETF)) + 1;
2713                     }
2714                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR)
2715                     {
2716                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMR)) + 1;
2717                     }
2718                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF)
2719                     {
2720                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMRWB_IETF)) + 1;
2721                     }
2722                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB)
2723                     {
2724                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_AMRWB)) + 1;
2725                     }
2726                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3)
2727                     {
2728                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_MP3)) + 1;
2729                     }
2730                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA)
2731                     {
2732                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_WMA)) + 1;
2733                     }
2734                     else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_REAL_AUDIO)
2735                     {
2736                         valuelen = oscl_strlen(_STRLIT_CHAR(PVMF_MIME_REAL_AUDIO)) + 1;
2737                     }
2738                     else
2739                     {
2740                         // Should not enter here
2741                         OSCL_ASSERT(false);
2742                         valuelen = 1;
2743                     }
2744
2745                     // Allocate memory for the strings
2746                     leavecode = OsclErrNone;
2747                     KeyVal.key = (char*) AllocateKVPKeyArray(leavecode, PVMI_KVPVALTYPE_CHARPTR, KeyLen);
2748                     if (OsclErrNone == leavecode)
2749                     {
2750                         KeyVal.value.pChar_value = (char*) AllocateKVPKeyArray(leavecode1, PVMI_KVPVALTYPE_CHARPTR, valuelen);
2751                     }
2752
2753                     if (OsclErrNone == leavecode && OsclErrNone == leavecode1)
2754                     {
2755                         // Copy the key string
2756                         oscl_strncpy(KeyVal.key, PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY, oscl_strlen(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) + 1);
2757                         oscl_strncat(KeyVal.key, PVOMXAUDIODECMETADATA_SEMICOLON, oscl_strlen(PVOMXAUDIODECMETADATA_SEMICOLON));
2758                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_STRING_CONSTCHAR));
2759                         oscl_strncat(KeyVal.key, PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR, oscl_strlen(PVMI_KVPVALTYPE_CHARPTR_STRING_CONSTCHAR));
2760                         KeyVal.key[KeyLen-1] = NULL_TERM_CHAR;
2761                         // Copy the value
2762                         if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM)
2763                         {
2764                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_LATM), valuelen);
2765                         }
2766                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO)
2767                         {
2768                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_MPEG4_AUDIO), valuelen);
2769                         }
2770                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640)
2771                         {
2772                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_3640), valuelen);
2773                         }
2774                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF)
2775                         {
2776                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_ADIF), valuelen);
2777                         }
2778                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO)
2779                         {
2780                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_ASF_MPEG4_AUDIO), valuelen);
2781                         }
2782                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2)
2783                         {
2784                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMR_IF2), valuelen);
2785                         }
2786                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF)
2787                         {
2788                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMR_IETF), valuelen);
2789                         }
2790                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR)
2791                         {
2792                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMR), valuelen);
2793                         }
2794                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF)
2795                         {
2796                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMRWB_IETF), valuelen);
2797                         }
2798                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB)
2799                         {
2800                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_AMRWB), valuelen);
2801                         }
2802                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3)
2803                         {
2804                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_MP3), valuelen);
2805                         }
2806                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA)
2807                         {
2808                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_WMA), valuelen);
2809                         }
2810                         else if (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_REAL_AUDIO)
2811                         {
2812                             oscl_strncpy(KeyVal.value.pChar_value, _STRLIT_CHAR(PVMF_MIME_REAL_AUDIO), valuelen);
2813                         }
2814                         else
2815                         {
2816                             // Should not enter here
2817                             OSCL_ASSERT(false);
2818                         }
2819                         KeyVal.value.pChar_value[valuelen-1] = NULL_TERM_CHAR;
2820                         // Set the length and capacity
2821                         KeyVal.length = valuelen;
2822                         KeyVal.capacity = valuelen;
2823                     }
2824                     else
2825                     {
2826                         // Memory allocation failed so clean up
2827                         if (KeyVal.key)
2828                         {
2829                             OSCL_ARRAY_DELETE(KeyVal.key);
2830                             KeyVal.key = NULL;
2831                         }
2832                         if (KeyVal.value.pChar_value)
2833                         {
2834                             OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
2835                         }
2836                         break;
2837                     }
2838                 }
2839             }
2840         }
2841
2842         if (KeyVal.key != NULL)
2843         {
2844             leavecode = OsclErrNone;
2845             leavecode = PushKVP(KeyVal, *valuelistptr);
2846             if (OsclErrNone != leavecode)
2847             {
2848                 switch (GetValTypeFromKeyString(KeyVal.key))
2849                 {
2850                     case PVMI_KVPVALTYPE_CHARPTR:
2851                         if (KeyVal.value.pChar_value != NULL)
2852                         {
2853                             OSCL_ARRAY_DELETE(KeyVal.value.pChar_value);
2854                             KeyVal.value.pChar_value = NULL;
2855                         }
2856                         break;
2857
2858                     default:
2859                         // Add more case statements if other value types are returned
2860                         break;
2861                 }
2862
2863                 OSCL_ARRAY_DELETE(KeyVal.key);
2864                 KeyVal.key = NULL;
2865             }
2866             else
2867             {
2868                 // Increment the counter for number of value entries added to the list
2869                 ++numentriesadded;
2870             }
2871
2872             // Check if the max number of value entries were added
2873             if (max_entries > 0 && numentriesadded >= max_entries)
2874             {
2875                 break;
2876             }
2877
2878         }
2879
2880     }
2881
2882     return PVMFSuccess;
2883
2884 }
2885
2886 /////////////////////////////////////////////////////////////////////////////
2887 bool PVMFOMXAudioDecNode::ReleaseAllPorts()
2888 {
2889     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::ReleaseAllPorts() In"));
2890
2891     if (iInPort)
2892     {
2893         iInPort->ClearMsgQueues();
2894         iInPort->Disconnect();
2895         OSCL_DELETE(((PVMFOMXDecPort*)iInPort));
2896         iInPort = NULL;
2897     }
2898
2899     if (iOutPort)
2900     {
2901         iOutPort->ClearMsgQueues();
2902         iOutPort->Disconnect();
2903         OSCL_DELETE(((PVMFOMXDecPort*)iOutPort));
2904         iOutPort = NULL;
2905     }
2906
2907     return true;
2908 }
2909
2910 /////////////////////////////////////////////////////////////////////////////
2911 PVMFStatus PVMFOMXAudioDecNode::CreateLATMParser()
2912 {
2913     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::CreateLATMParser() In"));
2914
2915     // First clean up if necessary
2916     DeleteLATMParser();
2917
2918     // Instantiate the LATM parser
2919     iLATMParser = OSCL_NEW(PV_LATM_Parser, ());
2920     if (!iLATMParser)
2921     {
2922         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::CreateLATMParser() LATM parser instantiation failed"));
2923         return PVMFErrNoMemory;
2924     }
2925
2926     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::CreateLATMParser() Out"));
2927     return PVMFSuccess;
2928 }
2929
2930 PVMFStatus PVMFOMXAudioDecNode::DeleteLATMParser()
2931 {
2932     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::DeleteLATMParser() In"));
2933
2934     // Delete LATM parser if there is one
2935     if (iLATMParser)
2936     {
2937         OSCL_DELETE(iLATMParser);
2938         iLATMParser = NULL;
2939     }
2940
2941     if (iLATMConfigBuffer)
2942     {
2943         oscl_free(iLATMConfigBuffer);
2944         iLATMConfigBuffer = NULL;
2945         iLATMConfigBufferSize = 0;
2946     }
2947
2948     PVLOGGER_LOGMSG(PVLOGMSG_INST_MLDBG, iLogger, PVLOGMSG_INFO, (0, "PVMFOMXAudioDecNode::DeleteLATMParser() Out"));
2949     return PVMFSuccess;
2950 }
2951
2952
2953
2954
2955
2956
2957 /////////////////////////////////////////////////////////////////////////////
2958 uint32 PVMFOMXAudioDecNode::GetNumMetadataKeys(char* aQueryKeyString)
2959 {
2960     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::GetNumMetadataKeys() called"));
2961
2962     // Update the available metadata keys
2963     iAvailableMetadataKeys.clear();
2964     int32 errcode = OsclErrNone;
2965     OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY));
2966
2967     if (iNumberOfAudioChannels > 0)
2968     {
2969         errcode = OsclErrNone;
2970         OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY));
2971     }
2972
2973     if (iPCMSamplingRate > 0)
2974     {
2975         errcode = OsclErrNone;
2976         OSCL_TRY(errcode, iAvailableMetadataKeys.push_back(PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY));
2977     }
2978
2979     uint32 num_entries = 0;
2980
2981     if (aQueryKeyString == NULL)
2982     {
2983         num_entries = iAvailableMetadataKeys.size();
2984     }
2985     else
2986     {
2987         for (uint32 i = 0; i < iAvailableMetadataKeys.size(); i++)
2988         {
2989             if (pv_mime_strcmp(iAvailableMetadataKeys[i].get_cstr(), aQueryKeyString) >= 0)
2990             {
2991                 num_entries++;
2992             }
2993         }
2994     }
2995     return num_entries; // Number of elements
2996
2997 }
2998
2999 /////////////////////////////////////////////////////////////////////////////
3000 uint32 PVMFOMXAudioDecNode::GetNumMetadataValues(PVMFMetadataList& aKeyList)
3001 {
3002     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::GetNumMetadataValues() called"));
3003
3004     uint32 numkeys = aKeyList.size();
3005
3006     if (numkeys <= 0)
3007     {
3008         // Don't do anything
3009         return 0;
3010     }
3011
3012     // Count the number of value entries for the provided key list
3013     uint32 numvalentries = 0;
3014     for (uint32 lcv = 0; lcv < numkeys; lcv++)
3015     {
3016         if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_CHANNELS_KEY) == 0))
3017         {
3018             // Channels
3019             if (iNumberOfAudioChannels > 0)
3020             {
3021                 ++numvalentries;
3022             }
3023         }
3024         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_SAMPLERATE_KEY) == 0) && (iPCMSamplingRate > 0))
3025         {
3026             // Sample rate
3027             ++numvalentries;
3028         }
3029         else if ((oscl_strcmp(aKeyList[lcv].get_cstr(), PVOMXAUDIODECMETADATA_CODECINFO_AUDIO_FORMAT_KEY) == 0) &&
3030                  iInPort != NULL)
3031         {
3032             // Format
3033             if ((((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_LATM) ||
3034                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MPEG4_AUDIO) ||
3035                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_3640) ||
3036                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ADIF) ||
3037                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_ASF_MPEG4_AUDIO) ||
3038                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IF2) ||
3039                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR_IETF) ||
3040                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMR) ||
3041                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB_IETF) ||
3042                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_AMRWB) ||
3043                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_MP3) ||
3044                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_WMA) ||
3045                     (((PVMFOMXDecPort*)iInPort)->iFormat == PVMF_MIME_REAL_AUDIO)
3046
3047                )
3048
3049             {
3050                 ++numvalentries;
3051             }
3052         }
3053     }
3054
3055     return numvalentries;
3056 }
3057
3058
3059 // needed for WMA parameter verification
3060 bool PVMFOMXAudioDecNode::VerifyParametersSync(PvmiMIOSession aSession, PvmiKvp* aParameters, int num_elements)
3061 {
3062     OSCL_UNUSED_ARG(aSession);
3063     OSCL_UNUSED_ARG(num_elements);
3064     if (pv_mime_strcmp(aParameters->key, PVMF_BITRATE_VALUE_KEY) == 0)
3065     {
3066         if (((PVMFOMXDecPort*)iOutPort)->verifyConnectedPortParametersSync(PVMF_BITRATE_VALUE_KEY, &(aParameters->value.uint32_value)) != PVMFSuccess)
3067         {
3068             return false;
3069         }
3070         return true;
3071     }
3072     else if (pv_mime_strcmp(aParameters->key, PVMF_FORMAT_SPECIFIC_INFO_KEY) < 0)
3073     {
3074         PVLOGGER_LOGMSG(PVLOGMSG_INST_REL, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::VerifyParametersSync() - Unsupported Key"));
3075         OSCL_ASSERT(false);
3076     }
3077
3078     bool cap_exchange_status = false;
3079
3080     pvAudioConfigParserInputs aInputs;
3081     OMXConfigParserInputs aInputParameters;
3082     AudioOMXConfigParserOutputs aOutputParameters;
3083
3084     aInputs.inPtr = (uint8*)(aParameters->value.key_specific_value);
3085     aInputs.inBytes = (int32)aParameters->capacity;
3086     aInputs.iMimeType = PVMF_MIME_WMA;
3087     aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.wma";
3088     aInputParameters.inBytes = aInputs.inBytes;
3089     aInputParameters.inPtr = aInputs.inPtr;
3090
3091
3092     if (aInputs.inBytes == 0 || aInputs.inPtr == NULL)
3093     {
3094         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::VerifyParametersSync() Codec Config data is not present"));
3095         return cap_exchange_status;
3096     }
3097
3098
3099     OMX_BOOL status = OMX_FALSE;
3100     OMX_U32 num_comps = 0, ii;
3101     OMX_STRING *CompOfRole;
3102     OMX_ERRORTYPE Err = OMX_ErrorNone;
3103     //  uint32 ii;
3104     // call once to find out the number of components that can fit the role
3105     Err = OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL);
3106
3107     if ((num_comps > 0) && (OMX_ErrorNone == Err))
3108     {
3109         CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING));
3110         for (ii = 0; ii < num_comps; ii++)
3111             CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
3112
3113         // call 2nd time to get the component names
3114         Err = OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole);
3115
3116         if (OMX_ErrorNone == Err)
3117         {
3118             for (ii = 0; ii < num_comps; ii++)
3119             {
3120                 aInputParameters.cComponentName = CompOfRole[ii];
3121                 status = OMX_MasterConfigParser(&aInputParameters, &aOutputParameters);
3122                 if (status == OMX_TRUE)
3123                 {
3124                     break;
3125                 }
3126                 else
3127                 {
3128                     status = OMX_FALSE;
3129                 }
3130             }
3131         }
3132
3133         // whether successful or not, need to free CompOfRoles
3134         for (ii = 0; ii < num_comps; ii++)
3135         {
3136             oscl_free(CompOfRole[ii]);
3137             CompOfRole[ii] = NULL;
3138         }
3139
3140         oscl_free(CompOfRole);
3141
3142     }
3143     else
3144     {
3145         // if no components support the role, nothing else to do
3146         return false;
3147     }
3148
3149     if (OMX_FALSE != status)
3150     {
3151         cap_exchange_status = true;
3152
3153         iPCMSamplingRate = aOutputParameters.SamplesPerSec;
3154         iNumberOfAudioChannels = aOutputParameters.Channels;
3155
3156         if ((iNumberOfAudioChannels != 1 && iNumberOfAudioChannels != 2) ||
3157                 (iPCMSamplingRate <= 0))
3158         {
3159             cap_exchange_status = false;
3160         }
3161     }
3162
3163     return cap_exchange_status;
3164
3165 }
3166
3167
3168 PVMFStatus PVMFOMXAudioDecNode::DoCapConfigVerifyParameters(PvmiKvp* aParameters, int aNumElements)
3169 {
3170     OSCL_UNUSED_ARG(aNumElements);
3171
3172     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3173                     (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() In"));
3174
3175     pvAudioConfigParserInputs aInputs;
3176     OMXConfigParserInputs aInputParameters;
3177     AudioOMXConfigParserOutputs aOutputParameters;
3178
3179     aInputs.inPtr = (uint8*)(aParameters->value.key_specific_value);
3180     aInputs.inBytes = (int32)aParameters->capacity;
3181     aInputs.iMimeType = iNodeConfig.iMimeType;
3182     aInputParameters.inBytes = aInputs.inBytes;
3183     aInputParameters.inPtr = aInputs.inPtr;
3184
3185     if (aInputs.inBytes == 0 || aInputs.inPtr == NULL)
3186     {
3187         // in case of following formats - config codec data is expected to
3188         // be present in the query. If not, config parser cannot be called
3189
3190         if (aInputs.iMimeType == PVMF_MIME_WMA ||
3191                 aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
3192                 aInputs.iMimeType == PVMF_MIME_3640 ||
3193                 aInputs.iMimeType == PVMF_MIME_LATM ||
3194                 aInputs.iMimeType == PVMF_MIME_ADIF ||
3195                 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
3196                 aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR ||
3197                 aInputs.iMimeType == PVMF_MIME_REAL_AUDIO)
3198         {
3199             if (aInputs.iMimeType == PVMF_MIME_LATM)
3200             {
3201                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() Codec Config data is not present"));
3202                 return PVMFErrNotSupported;
3203             }
3204             else
3205             {
3206                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() Codec Config data is not present"));
3207
3208                 // DV TO_DO: remove this
3209                 OSCL_LEAVE(OsclErrNotSupported);
3210             }
3211         }
3212     }
3213
3214     // in case of ASF_MPEG4 audio need to create aac config header
3215     if (aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO)
3216     {
3217         if (!CreateAACConfigDataFromASF(aInputParameters.inPtr, aInputParameters.inBytes, &iAACConfigData[0], iAACConfigDataLength))
3218         {
3219             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
3220                             (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() - Error in creating AAC Codec Config data"));
3221
3222
3223             return PVMFErrNotSupported;
3224         }
3225
3226         aInputParameters.inPtr = &iAACConfigData[0];
3227         aInputParameters.inBytes = iAACConfigDataLength;
3228     }
3229
3230
3231     if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
3232             aInputs.iMimeType == PVMF_MIME_3640 ||
3233             aInputs.iMimeType == PVMF_MIME_LATM ||
3234             aInputs.iMimeType == PVMF_MIME_ADIF ||
3235             aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
3236             aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR)
3237     {
3238         aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.aac";
3239     }
3240     // AMR
3241     else if (aInputs.iMimeType == PVMF_MIME_AMR_IF2 ||
3242              aInputs.iMimeType == PVMF_MIME_AMR_IETF ||
3243              aInputs.iMimeType == PVMF_MIME_AMR)
3244     {
3245         aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrnb";
3246     }
3247     else if (aInputs.iMimeType == PVMF_MIME_AMRWB_IETF ||
3248              aInputs.iMimeType == PVMF_MIME_AMRWB)
3249     {
3250         aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrwb";
3251     }
3252     else if (aInputs.iMimeType == PVMF_MIME_MP3)
3253     {
3254         aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.mp3";
3255     }
3256     else if (aInputs.iMimeType ==  PVMF_MIME_WMA)
3257     {
3258         aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.wma";
3259     }
3260     else if (aInputs.iMimeType ==  PVMF_MIME_REAL_AUDIO)
3261     {
3262         aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.ra";
3263     }
3264     else
3265     {
3266         // Illegal codec specified.
3267         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() Input port format other then codec type", iName.Str()));
3268     }
3269
3270     OMX_BOOL status = OMX_FALSE;
3271     OMX_U32 num_comps = 0, ii;
3272     OMX_STRING *CompOfRole;
3273     OMX_ERRORTYPE Err = OMX_ErrorNone;
3274     //  uint32 ii;
3275     // call once to find out the number of components that can fit the role
3276     Err = OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL);
3277
3278     if ((num_comps > 0) && (OMX_ErrorNone == Err))
3279     {
3280         CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING));
3281         for (ii = 0; ii < num_comps; ii++)
3282             CompOfRole[ii] = (OMX_STRING) oscl_malloc(PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
3283
3284         // call 2nd time to get the component names
3285         Err = OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole);
3286
3287         if (OMX_ErrorNone == Err)
3288         {
3289             for (ii = 0; ii < num_comps; ii++)
3290             {
3291                 aInputParameters.cComponentName = CompOfRole[ii];
3292                 status = OMX_MasterConfigParser(&aInputParameters, &aOutputParameters);
3293                 if (status == OMX_TRUE)
3294                 {
3295                     break;
3296                 }
3297                 else
3298                 {
3299                     status = OMX_FALSE;
3300                 }
3301             }
3302         }
3303
3304         // whether successful or not, need to free CompOfRoles
3305         for (ii = 0; ii < num_comps; ii++)
3306         {
3307             oscl_free(CompOfRole[ii]);
3308             CompOfRole[ii] = NULL;
3309         }
3310
3311         oscl_free(CompOfRole);
3312
3313     }
3314     else
3315     {
3316         // if no component supports the role, nothing else to do
3317         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3318                         (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() No omx component supports this role PVMFErrNotSupported"));
3319         return PVMFErrNotSupported;
3320     }
3321
3322     if (status == OMX_FALSE)
3323     {
3324         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3325                         (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() ->OMXConfigParser() PVMFErrNotSupported"));
3326         return PVMFErrNotSupported;
3327     }
3328
3329     if (aInputs.iMimeType == PVMF_MIME_WMA)
3330     {
3331         iNumberOfAudioChannels = aOutputParameters.Channels;
3332         iPCMSamplingRate = aOutputParameters.SamplesPerSec;
3333     }
3334     else if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
3335              aInputs.iMimeType == PVMF_MIME_3640 ||
3336              aInputs.iMimeType == PVMF_MIME_LATM ||
3337              aInputs.iMimeType == PVMF_MIME_ADIF ||
3338              aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
3339              aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR)
3340     {
3341         iNumberOfAudioChannels = aOutputParameters.Channels;
3342         iPCMSamplingRate = aOutputParameters.SamplesPerSec;
3343     }
3344
3345     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3346                     (0, "PVMFOMXAudioDecNode::DoCapConfigVerifyParameters() Out"));
3347     return PVMFSuccess;
3348 }
3349
3350 void PVMFOMXAudioDecNode::DoCapConfigSetParameters(PvmiKvp* aParameters, int aNumElements, PvmiKvp* &aRetKVP)
3351 {
3352     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3353                     (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() In"));
3354
3355     if (aParameters == NULL || aNumElements < 1)
3356     {
3357         aRetKVP = aParameters;
3358         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() Passed in parameter invalid"));
3359         return;
3360     }
3361
3362     int32 ii;
3363
3364     for (ii = 0; ii < aNumElements; ii ++)
3365     {
3366
3367         // find out if the audio dec format key is used for the query
3368         if (pv_mime_strcmp(aParameters[ii].key, PVMF_FORMAT_SPECIFIC_INFO_KEY) == 0)
3369         {
3370
3371             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3372                             (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() set audio format specific info"));
3373
3374             if (iTrackUnderVerificationConfig)
3375             {
3376                 oscl_free(iTrackUnderVerificationConfig);
3377                 iTrackUnderVerificationConfig = NULL;
3378                 iTrackUnderVerificationConfigSize = 0;
3379             }
3380
3381             iTrackUnderVerificationConfigSize = aParameters[ii].capacity;
3382
3383             if (iTrackUnderVerificationConfigSize > 0)
3384             {
3385                 iTrackUnderVerificationConfig = (uint8*)(oscl_malloc(sizeof(uint8) * iTrackUnderVerificationConfigSize));
3386                 oscl_memcpy(iTrackUnderVerificationConfig, aParameters[ii].value.key_specific_value, iTrackUnderVerificationConfigSize);
3387             }
3388
3389         }
3390         else if (pv_mime_strcmp(aParameters[ii].key,  _STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) == 0)
3391         {
3392             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3393                             (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() set preferred omx component list"));
3394
3395
3396             // each kvp paramater corresponds to one omx component - a new item in the vector is created
3397
3398             iOMXPreferredComponentOrderVec.push_back((OMX_STRING)(aParameters[ii].value.pChar_value));
3399
3400
3401         }
3402         else if (pv_mime_strcmp(aParameters[ii].key, PVMF_AUDIO_DEC_FORMAT_TYPE_VALUE_KEY) == 0)
3403         {
3404             // set the mime type if audio format is being used
3405             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3406                             (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() set audio dec format type to %s", aParameters->value.pChar_value));
3407
3408             iNodeConfig.iMimeType = aParameters[ii].value.pChar_value;
3409         }
3410         else if (pv_mime_strcmp(aParameters[ii].key, PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY) == 0)
3411         {
3412             // set the mime type if audio format is being used
3413             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3414                             (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() set audio dec pcm buffer size to %d milliseconds", aParameters->value.uint32_value));
3415
3416             iOutputBufferPCMDuration = aParameters[ii].value.uint32_value;
3417             if (iOutputBufferPCMDuration == 0)
3418             {
3419
3420                 aRetKVP = aParameters; // indicate "error" by setting return KVP to original
3421                 iOutputBufferPCMDuration = PVOMXAUDIODEC_DEFAULT_OUTPUTPCM_TIME;
3422
3423                 PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3424                                 (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() set audio dec pcm buffer size to 0 milliseconds not allowed, reveting to default of %d", iOutputBufferPCMDuration));
3425
3426             }
3427
3428         }
3429         else if (pv_mime_strcmp(aParameters[ii].key, PVMF_AUDIO_SILENCE_INSERTION_KEY) == 0)
3430         {
3431             // Enable or Disable silence insertion in audio tracks
3432             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3433                             (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() Silence insertion key \n"));
3434
3435             iSilenceInsertionFlag = aParameters[ii].value.bool_value;
3436         }
3437         else
3438         {
3439             // For now, ignore other queries
3440             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3441                             (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() Key not used"));
3442
3443             // indicate "error" by setting return KVP to the original
3444             aRetKVP = aParameters;
3445             break;
3446         }
3447     }
3448
3449
3450
3451     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3452                     (0, "PVMFOMXAudioDecNode::DoCapConfigSetParameters() Out"));
3453 }
3454
3455 void PVMFOMXAudioDecNode::CalculateBOCParameters()
3456 {
3457     OSCL_ASSERT(iBOCReceived);
3458
3459     iBOCBytesToSkip = iBOCSamplesToSkip * iNumberOfAudioChannels * 2; // assuming 16-bit data
3460     iBOCBeginningOfContentTS = iBOCTimeStamp + ((iBOCSamplesToSkip * iInTimeScale + iPCMSamplingRate - 1) / iPCMSamplingRate);
3461 }
3462
3463 void PVMFOMXAudioDecNode::HandleBOCProcessing(OMX_BUFFERHEADERTYPE* aBuffer)
3464 {
3465     if (aBuffer->nTimeStamp > (((int64)iBOCBeginningOfContentTS *(int64)iTimeScale) / (int64)iInTimeScale))
3466     {
3467         // buffer time stamp is passed the beginning of content time stamp before dropping all BOC samples
3468         // this is most likely due to a reposition during the BOC silence dropping
3469         iBOCReceived = false;
3470
3471         return;
3472     }
3473
3474     if (iBOCBytesToSkip < aBuffer->nFilledLen)
3475     {
3476         aBuffer->nOffset += iBOCBytesToSkip;
3477         aBuffer->nFilledLen -= iBOCBytesToSkip;
3478
3479         iBOCBytesToSkip = 0;
3480         iBOCReceived = false;
3481
3482         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3483                         (0, "PVMFOMXAudioDecNode::HandleBOCProcessing: Dropping %d samples from buffer %x due to BOC", iBOCSamplesToSkip, (OsclAny*) aBuffer->pAppPrivate));
3484     }
3485     else
3486     {
3487         iBOCBytesToSkip -= aBuffer->nFilledLen;
3488         aBuffer->nFilledLen = 0;
3489
3490         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3491                         (0, "PVMFOMXAudioDecNode::HandleBOCProcessing: Dropping %d samples (the entire buffer) from buffer %x due to BOC.  There are %d samples more to drop.", aBuffer->nFilledLen, (OsclAny*) aBuffer->pAppPrivate, iBOCSamplesToSkip));
3492     }
3493 }
3494
3495 void PVMFOMXAudioDecNode::CalculateEOCParameters()
3496 {
3497     OSCL_ASSERT(iEOCReceived);
3498
3499     // calculate the total number of frames
3500     // timestamp is from media msg, therefore in milliseconds
3501     uint32 totalFrames = (uint32)(((int64)(iEOCTimeStamp - iTSOfFirstDataMsgAfterBOS) * (int64)iPCMSamplingRate + (((int64)iInTimeScale * (int64)iSamplesPerFrame) >> 1)) / ((int64)iInTimeScale * (int64)iSamplesPerFrame) + iEOCFramesToFollow); // round to frame boundaries
3502
3503     // calculate the frame at which silence removal should begin
3504     iEOCSilenceRemovalStartFrame = totalFrames - ((iEOCSamplesToSkip + iSamplesPerFrame - 1) / iSamplesPerFrame);
3505
3506     // calculate the offset in samples within the frame at which silence removal should begin
3507     iEOCSilenceRemovalSampleOffset = iSamplesPerFrame - (iEOCSamplesToSkip % iSamplesPerFrame);
3508 }
3509
3510 void PVMFOMXAudioDecNode::HandleEOCProcessing(OMX_BUFFERHEADERTYPE* aBuffer)
3511 {
3512     uint32 bytesPerSample = 2; // assuming 16-bit data
3513     uint32 bufferLengthSamples = aBuffer->nFilledLen / (bytesPerSample * iNumberOfAudioChannels);
3514
3515     if (iBufferContainsIntFrames)
3516     {
3517         uint32 outputBufferStartFrame;
3518         uint32 outputBufferEndFrame;
3519         uint32 framesInBuffer;
3520
3521         // calculate everything in frames, since timestamps won't be sample accurate.
3522         // also assume that there is always an integer number of frames per buffer.
3523         // note: timestamp is from OMX buffer, therefore in microseconds
3524         // note: frames are 0-indexed here
3525         int64 normTS = aBuffer->nTimeStamp - (((int64)iTSOfFirstDataMsgAfterBOS * (int64)iTimeScale) / (int64)iInTimeScale);
3526         outputBufferStartFrame = (uint32)((normTS * (int64)iPCMSamplingRate + (((int64)iTimeScale * (int64)iSamplesPerFrame) >> 1)) / ((int64)iTimeScale * (int64)iSamplesPerFrame)); // round to frame boundaries
3527         framesInBuffer = bufferLengthSamples / iSamplesPerFrame; // no rounding needed since length should be an integer number of frames
3528
3529         OSCL_ASSERT((bufferLengthSamples % iSamplesPerFrame) == 0); // double check
3530
3531         outputBufferEndFrame = outputBufferStartFrame + framesInBuffer - 1;
3532
3533         // check to see if silence removal begins within this buffer
3534         if (outputBufferEndFrame >= iEOCSilenceRemovalStartFrame)
3535         {
3536             uint32 validSamples;
3537             uint32 newFilledLen;
3538             uint32 skippedSamples;
3539
3540             validSamples = OSCL_MAX((int32) iEOCSilenceRemovalStartFrame - (int32)outputBufferStartFrame, 0) * iSamplesPerFrame + iEOCSilenceRemovalSampleOffset;
3541             newFilledLen = validSamples * bytesPerSample * iNumberOfAudioChannels;
3542             skippedSamples = bufferLengthSamples - validSamples;
3543
3544             iEOCSamplesToSkip = OSCL_MAX((int32) iEOCSamplesToSkip - (int32) skippedSamples, 0);
3545
3546             if (iEOCSamplesToSkip == 0)
3547             {
3548                 iEOCReceived = false;
3549             }
3550             else
3551             {
3552                 // update start point information
3553                 iEOCSilenceRemovalSampleOffset += skippedSamples;
3554
3555                 iEOCSilenceRemovalStartFrame += iEOCSilenceRemovalSampleOffset / iSamplesPerFrame;
3556                 iEOCSilenceRemovalSampleOffset = iEOCSilenceRemovalSampleOffset % iSamplesPerFrame;
3557             }
3558
3559             OSCL_ASSERT(newFilledLen <= aBuffer->nFilledLen);
3560
3561             aBuffer->nFilledLen = newFilledLen;
3562
3563             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3564                             (0, "PVMFOMXAudioDecNode::HandleEOCProcessing: Dropping %d samples from buffer %x due to EOC", skippedSamples, (OsclAny*) aBuffer->pAppPrivate));
3565         }
3566     }
3567     else
3568     {
3569         // the method for gapless silence removal without int frames per buffer isn't guaranteed to be sample accurate
3570
3571         uint32 outputBufferStartSample;
3572         uint32 outputBufferEndSample;
3573         uint32 EOCSilenceRemovalStartSample = (iEOCSilenceRemovalStartFrame * iSamplesPerFrame) + iEOCSilenceRemovalSampleOffset;
3574
3575         // find the difference between the time based off of timestamps and that based off of accumulated samples
3576         // the timestamps have a max error dependent on their resolution (timescale) equivalent to: ceil(sampling_rate / timescale)
3577         // if the accumulated sample count is within this max error then most likely no data has been dropped, and the accumulated sample
3578         // count is more accurate than the timestamps.  however, if it is outside of that error window then we should use the
3579         // calculation based off of the timestamps; since while the ts calculation may not be sample accurate, it will be more accurate
3580         // than the accumulated sample count in the case of dropped data
3581         int64 normTS = aBuffer->nTimeStamp - (((int64)iTSOfFirstDataMsgAfterBOS * (int64)iTimeScale) / (int64)iInTimeScale);
3582
3583         int32 sampleDelta = (int32)(((normTS * (int64)iPCMSamplingRate) / (int64)iTimeScale) - (iClipSampleCount - bufferLengthSamples));
3584         int32 tsMaxError = (iPCMSamplingRate + (iInTimeScale - 1)) / iInTimeScale;
3585
3586         if (oscl_abs(sampleDelta) < tsMaxError)
3587         {
3588             // use accumulated sample count based calculation
3589
3590             outputBufferStartSample = iClipSampleCount - bufferLengthSamples;
3591             outputBufferEndSample = iClipSampleCount;
3592         }
3593         else
3594         {
3595             // some data must have been dropped, use the timestamp based calculation
3596
3597             outputBufferStartSample = (uint32)((normTS * (int64)iPCMSamplingRate) / (int64)iTimeScale);
3598             outputBufferEndSample = outputBufferStartSample + bufferLengthSamples;
3599         }
3600
3601
3602         // check to see if silence removal begins within this buffer
3603         if (outputBufferEndSample >= EOCSilenceRemovalStartSample)
3604         {
3605             uint32 validSamples;
3606             uint32 newFilledLen;
3607             uint32 skippedSamples;
3608
3609             validSamples = OSCL_MAX((int32)EOCSilenceRemovalStartSample - (int32) outputBufferStartSample, 0);
3610             newFilledLen = validSamples * bytesPerSample * iNumberOfAudioChannels;
3611             skippedSamples = bufferLengthSamples - validSamples;
3612
3613             iEOCSamplesToSkip = OSCL_MAX((int32) iEOCSamplesToSkip - (int32) skippedSamples, 0);
3614
3615             if (iEOCSamplesToSkip == 0)
3616             {
3617                 iEOCReceived = false;
3618             }
3619             else
3620             {
3621                 // update start point information
3622                 iEOCSilenceRemovalSampleOffset += skippedSamples;
3623
3624                 iEOCSilenceRemovalStartFrame += iEOCSilenceRemovalSampleOffset / iSamplesPerFrame;
3625                 iEOCSilenceRemovalSampleOffset = iEOCSilenceRemovalSampleOffset % iSamplesPerFrame;
3626             }
3627
3628             OSCL_ASSERT(newFilledLen <= aBuffer->nFilledLen);
3629
3630             aBuffer->nFilledLen = newFilledLen;
3631
3632             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3633                             (0, "PVMFOMXAudioDecNode::HandleEOCProcessing: Dropping %d samples from buffer %x due to EOC", skippedSamples, (OsclAny*) aBuffer->pAppPrivate));
3634         }
3635     }
3636
3637 }
3638
3639 PVMFStatus PVMFOMXAudioDecNode::RetrieveMP3FrameLength(uint8 *pBuffer)
3640 {
3641
3642     PVMFStatus err = PVMFSuccess;
3643     uint32  temp;
3644     uint8  tmp1;
3645     uint8  tmp2;
3646     uint8  tmp3;
3647     uint8  tmp4;
3648     uint32  version;
3649
3650     /*
3651      *  MPEG Audio Version ID
3652      */
3653     tmp1 = *pBuffer;
3654     tmp2 = *(pBuffer + 1);
3655     tmp3 = *(pBuffer + 2);
3656     tmp4 = *(pBuffer + 3);
3657
3658     temp = ((((uint32)(tmp1)) << 24) |
3659             (((uint32)(tmp2)) << 16) |
3660             (((uint32)(tmp3)) <<  8) |
3661             (((uint32)(tmp4))));
3662
3663     if (((temp >> 21) & MP3_SYNC_WORD) != MP3_SYNC_WORD)
3664     {
3665         return PVMFErrCorrupt;
3666     }
3667
3668     temp = (temp << 11) >> 11;
3669
3670
3671     switch (temp >> 19)  /* 2 */
3672     {
3673         case 0:
3674             version = MPEG_2_5;
3675             break;
3676         case 2:
3677             version = MPEG_2;
3678             break;
3679         case 3:
3680             version = MPEG_1;
3681             break;
3682         default:
3683             version = INVALID_VERSION;
3684             err = PVMFErrNotSupported;
3685             break;
3686     }
3687
3688
3689
3690     iSamplesPerFrame = (version == MPEG_1) ?
3691                        2 * MP3_SUBBANDS_NUMBER * MP3_FILTERBANK_BANDS :
3692                        MP3_SUBBANDS_NUMBER * MP3_FILTERBANK_BANDS;
3693
3694     return err;
3695 }
3696
3697 PVMFStatus PVMFOMXAudioDecNode::CountSamplesInBuffer(OMX_BUFFERHEADERTYPE* aBuffer)
3698 {
3699     if (aBuffer->nTimeStamp < (((int64)iTSOfFirstDataMsgAfterBOS *(int64)iTimeScale) / (int64)iInTimeScale))
3700     {
3701         // time stamp is before BOS (i.e. the buffer could be from the port flush)
3702         // therefore don't count this buffer
3703         return PVMFSuccess;
3704     }
3705
3706     uint32 bytesPerSample = 2; // assuming 16-bit data
3707
3708     if ((0 == iNumberOfAudioChannels) ||
3709             (0 == iSamplesPerFrame))
3710     {
3711         return PVMFFailure;
3712     }
3713
3714     uint32 samplesInBuffer = aBuffer->nFilledLen / (bytesPerSample * iNumberOfAudioChannels);
3715
3716     // one way toggle
3717     if ((0 != (samplesInBuffer % iSamplesPerFrame)) && (iBufferContainsIntFrames == true))
3718     {
3719         iBufferContainsIntFrames = false;
3720     }
3721
3722     iClipSampleCount += samplesInBuffer;
3723
3724     return PVMFSuccess;
3725 }
3726
3727 // needed for AAC in ASF
3728 typedef enum
3729 {
3730     AAC_LC = 1, // should map to 2
3731     AAC_LTP = 3 // should map to 4
3732 } PROFILE_TYPES;
3733
3734 typedef enum
3735 {
3736     AAC_LC_SBR = 5 // should map to 5
3737     , ENHANCED_AAC_LC_SBR_PS // should map to 29
3738     , INVALID_OBJ_TYPE = 0xffffffff
3739 } EXTERNAL_OBJECT_TYPES;
3740
3741 typedef enum
3742 {
3743     AOT_NULL_OBJECT      = 0,
3744     AOT_AAC_LC           = 2,   // LC
3745     AOT_AAC_LTP          = 4,   // LTP
3746     AOT_SBR              = 5,   // SBR
3747     AOT_PS               = 29,  // PS
3748
3749 } eAUDIO_OBJECT_TYPE;
3750
3751 static const uint32 srIndexTable[16] = {96000, 88200, 64000, 48000, 44100,
3752                                         32000, 24000, 22050, 16000, 12000,
3753                                         11025,  8000,  7350,  0, 0, 0
3754                                        };
3755
3756
3757 bool PVMFOMXAudioDecNode::CreateAACConfigDataFromASF(uint8 *inptr, uint32 inlen, uint8 *outptr, uint32 &outlen)
3758 {
3759
3760     if (NULL == inptr || inlen < 20)
3761     {
3762         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3763                         (0, "PVMFOMXAudioDecNode::CreateAACConfigDataFromASF() Error - insufficient config data"));
3764
3765         return false;
3766     }
3767
3768
3769
3770     uint32 *valPtr = OSCL_STATIC_CAST(uint32 *, inptr);
3771     EXTERNAL_OBJECT_TYPES ExternlObjType = INVALID_OBJ_TYPE;
3772     eAUDIO_OBJECT_TYPE objType = AOT_NULL_OBJECT;
3773
3774     uint32 OutSampRate = 0;
3775     uint32 SamplingRate = 0;
3776     uint32 NumChannels = 0;  /* checks below assume unsigned type
3777                               * (i.e., less than 0 not explicitly
3778                               * checked, so don't change to signed.
3779                               */
3780     uint32 SamplesPerFrame = 0;
3781
3782     valPtr++; // this field represents frame length in bytes (we're not interested right now)
3783     // e.g. if there's 1024 samples per frame stereo, frame length is 4096 (2x2x1024)
3784     SamplesPerFrame = *valPtr++; // read number of samples per frame (1024 or 2048)
3785     SamplingRate = *valPtr++;
3786     NumChannels = *valPtr++;
3787
3788     PROFILE_TYPES profile = OSCL_STATIC_CAST(PROFILE_TYPES, *valPtr++);
3789
3790     if (inlen > 20)
3791     {
3792         OutSampRate = *valPtr++;
3793         ExternlObjType = OSCL_STATIC_CAST(EXTERNAL_OBJECT_TYPES, *valPtr++);
3794         // the next field is the Down sampling mode - which we dont care about here
3795         //iDownSampMode = *valPtr++;
3796     }
3797
3798
3799     // Now - need to convert the ASF External obj type into proper AAC decoder audio obj type
3800
3801     if (INVALID_OBJ_TYPE == ExternlObjType)
3802     {
3803         objType = OSCL_STATIC_CAST(eAUDIO_OBJECT_TYPE, profile + 1);
3804         OutSampRate = SamplingRate;
3805     }
3806     else if (AAC_LC_SBR == ExternlObjType)
3807     {
3808         objType = AOT_SBR;
3809     }
3810     else if (ENHANCED_AAC_LC_SBR_PS == ExternlObjType)
3811     {
3812         objType =  AOT_PS;
3813     }
3814     else
3815     {
3816         objType = OSCL_STATIC_CAST(eAUDIO_OBJECT_TYPE, profile + 1);
3817         OutSampRate = SamplingRate;
3818     }
3819
3820     uint32 framelength = 1024; // hardcode to fit plain AAC case - since we use plain aac sampling rate as well
3821     int32 i;
3822
3823
3824     uint8 *aConfigHeader = outptr;
3825
3826     /* Write AOT */
3827     if (objType > AOT_PS)
3828     {
3829         return false;
3830     }
3831
3832     aConfigHeader[0] = (uint8)(objType << 3);   /* AudioObjectType  5 bits */
3833
3834     /* Write Sampling frequency */
3835     for (i = 0; i < 15; i++)
3836     {
3837         if (srIndexTable[i] ==  SamplingRate)
3838         {
3839             break;
3840         }
3841     }
3842
3843     if (i > 13)
3844     {
3845         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3846                         (0, "PVMFOMXAudioDecNode::CreateAACConfigDataFromASF() Error - unsupported sampling rate"));
3847
3848         return false;
3849     }
3850
3851     aConfigHeader[0] |= (uint8)(i >> 1);    /* SamplingRate  3 of 4 bits */
3852     aConfigHeader[1]  = (uint8)(i << 7);    /* SamplingRate  1 of 4 bits */
3853
3854     /* Write Number of Channels */
3855     // NumChannels is unsigned so can't be less than 0
3856     // only need to check if the value is too large.
3857     if ((NumChannels > 2))
3858     {
3859         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3860                         (0, "PVMFOMXAudioDecNode::CreateAACConfigDataFromASF() Error - unsupported number of channels"));
3861
3862         return false;
3863     }
3864
3865
3866     aConfigHeader[1] |= (uint8)(NumChannels << 3);   /* NumChannels  4 of 4 bits */
3867
3868
3869     /* detect extension AOT */
3870     if ((objType == AOT_SBR) || (objType == AOT_PS))
3871     {
3872         /* Write Final Sampling frequency */
3873
3874         for (i = 0; i < 15; i++)
3875         {
3876             if (srIndexTable[i] == OutSampRate)
3877             {
3878                 break;
3879             }
3880         }
3881
3882         if (i > 13)
3883         {
3884             PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
3885                             (0, "PVMFOMXAudioDecNode::CreateAACConfigDataFromASF() Error - unsupported sampling rate"));
3886
3887             return false;
3888         }
3889
3890         aConfigHeader[1] |= (uint8)(i >> 1);   /* SamplingRate  1 of 4 bits */
3891         aConfigHeader[2]  = (uint8)(i << 7);   /* SamplingRate  3 of 4 bits */
3892
3893         aConfigHeader[2] |= (uint8)((AOT_AAC_LC) << 2);  /* external AudioObjectType  5 bits */
3894
3895         aConfigHeader[3]  = (framelength == 960) ? 4 : 0;      /* framelength  1 of 1 bits (shifted) */
3896         aConfigHeader[3] |=  0;        /* dependsOnCoreCoder 1 bits, 0, see ISO/IEC 14496-3 Subpart 4, 4.4.1 */
3897         aConfigHeader[3] |=  0;        /* Extension Flag: Shall be 0 for supported aot */
3898
3899         outlen = 4;
3900
3901     }
3902     else
3903     {
3904         aConfigHeader[1] |= (framelength == 960) ? 4 : 0;      /* framelength  1 of 1 bits (shifted) */
3905
3906         aConfigHeader[1] |=  0;        /* dependsOnCoreCoder 1 bits, 0, see ISO/IEC 14496-3 Subpart 4, 4.4.1 */
3907         aConfigHeader[1] |=  0;        /* Extension Flag: Shall be 0 for supported aot */
3908
3909         outlen = 2;
3910     }
3911
3912
3913     return true;
3914 }
3915
3916
3917 PVMFStatus PVMFOMXAudioDecNode::DoCapConfigReleaseParameters(PvmiKvp* aParameters, int aNumElements)
3918 {
3919     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::DoCapConfigReleaseParameters() In"));
3920
3921     if (aParameters == NULL || aNumElements < 1)
3922     {
3923         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoCapConfigReleaseParameters() KVP list is NULL or number of elements is 0"));
3924         return PVMFErrArgument;
3925     }
3926
3927
3928     if (pv_mime_strcmp(aParameters[0].key, _STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) == 0)
3929     {
3930         // everything was allocated in blocks, so it's enough to release the beginning
3931         oscl_free(aParameters[0].key);
3932         oscl_free(aParameters[0].value.pChar_value);
3933         // Free memory for the parameter list
3934         oscl_free(aParameters);
3935         aParameters = NULL;
3936
3937         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::DoCapConfigReleaseParameters() Out"));
3938         return PVMFSuccess;
3939     }
3940     else if (pv_mime_strcmp(aParameters[0].key, _STRLIT_CHAR(PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY)) == 0)
3941     {
3942         oscl_free(aParameters[0].key);
3943         oscl_free(aParameters);
3944         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::DoCapConfigReleaseParameters() Out"));
3945         return PVMFSuccess;
3946     }
3947
3948
3949     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoCapConfigReleaseParameters() KVP list is NULL or number of elements is 0"));
3950     return PVMFErrArgument;
3951 }
3952
3953 PVMFStatus PVMFOMXAudioDecNode::DoCapConfigGetParametersSync(PvmiKeyType aIdentifier, PvmiKvp*& aParameters, int& aNumParamElements, PvmiCapabilityContext aContext)
3954 {
3955     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXAudioDecNode::DoCapConfigGetParametersSync() In"));
3956     OSCL_UNUSED_ARG(aContext);
3957
3958     // Initialize the output parameters
3959     aNumParamElements = 0;
3960     aParameters = NULL;
3961
3962     if (pv_mime_strcmp(aIdentifier, _STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) == 0)
3963     {
3964         // get the list of omx components that support the track.
3965         // Track config info and mime type was previously set through capconfig - setparametersync
3966
3967         pvAudioConfigParserInputs aInputs;
3968         OMXConfigParserInputs aInputParameters;
3969         AudioOMXConfigParserOutputs aOutputParameters;
3970
3971         aInputs.inPtr = (uint8*) iTrackUnderVerificationConfig;
3972         aInputs.inBytes = (int32) iTrackUnderVerificationConfigSize;
3973         aInputs.iMimeType = iNodeConfig.iMimeType;
3974
3975         aInputParameters.inBytes = aInputs.inBytes;
3976         aInputParameters.inPtr = aInputs.inPtr;
3977
3978         if (aInputs.inBytes == 0 || aInputs.inPtr == NULL)
3979         {
3980             // in case of following formats - config codec data is expected to
3981             // be present in the query. If not, config parser cannot be called
3982
3983             if (aInputs.iMimeType == PVMF_MIME_WMA ||
3984                     aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
3985                     aInputs.iMimeType == PVMF_MIME_3640 ||
3986                     aInputs.iMimeType == PVMF_MIME_LATM ||
3987                     aInputs.iMimeType == PVMF_MIME_ADIF ||
3988                     aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
3989                     aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR)
3990             {
3991
3992                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXAudioDecNode::DoCapConfigGetParameters() Codec Config data is not present"));
3993                 return PVMFErrNotSupported;
3994
3995             }
3996         }
3997
3998
3999         // in case of ASF_MPEG4 audio need to create aac config header
4000         if (aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO)
4001         {
4002             if (!CreateAACConfigDataFromASF(aInputParameters.inPtr, aInputParameters.inBytes, &iAACConfigData[0], iAACConfigDataLength))
4003             {
4004                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR,
4005                                 (0, "PVMFOMXAudioDecNode::DoCapConfigGetParameters() - Error in creating AAC Codec Config data"));
4006
4007
4008                 return PVMFErrNotSupported;
4009             }
4010
4011             aInputParameters.inPtr = &iAACConfigData[0];
4012             aInputParameters.inBytes = iAACConfigDataLength;
4013         }
4014
4015
4016         if (aInputs.iMimeType == PVMF_MIME_MPEG4_AUDIO ||
4017                 aInputs.iMimeType == PVMF_MIME_3640 ||
4018                 aInputs.iMimeType == PVMF_MIME_LATM ||
4019                 aInputs.iMimeType == PVMF_MIME_ADIF ||
4020                 aInputs.iMimeType == PVMF_MIME_ASF_MPEG4_AUDIO ||
4021                 aInputs.iMimeType == PVMF_MIME_AAC_SIZEHDR)
4022         {
4023             aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.aac";
4024         }
4025         // AMR
4026         else if (aInputs.iMimeType == PVMF_MIME_AMR_IF2 ||
4027                  aInputs.iMimeType == PVMF_MIME_AMR_IETF ||
4028                  aInputs.iMimeType == PVMF_MIME_AMR)
4029         {
4030             aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrnb";
4031         }
4032         else if (aInputs.iMimeType == PVMF_MIME_AMRWB_IETF ||
4033                  aInputs.iMimeType == PVMF_MIME_AMRWB)
4034         {
4035             aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.amrwb";
4036         }
4037         else if (aInputs.iMimeType == PVMF_MIME_MP3)
4038         {
4039             aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.mp3";
4040         }
4041         else if (aInputs.iMimeType ==  PVMF_MIME_WMA)
4042         {
4043             aInputParameters.cComponentRole = (OMX_STRING)"audio_decoder.wma";
4044         }
4045         else
4046         {
4047             // Illegal codec specified.
4048             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::PVMFOMXAudioDecNode::DoCapConfigGetParameters() Input port format other then codec type", iName.Str()));
4049             return PVMFErrNotSupported;
4050         }
4051
4052
4053
4054
4055         OMX_BOOL status = OMX_FALSE;
4056         OMX_U32 num_comps = 0;
4057         OMX_STRING *CompOfRole;
4058         OMX_U32 ii;
4059         OMX_ERRORTYPE Err = OMX_ErrorNone;
4060
4061         // call once to find out the number of components that can fit the role
4062         Err = OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, NULL);
4063
4064
4065
4066
4067         if ((num_comps > 0) && (OMX_ErrorNone == Err))
4068         {
4069             // allocate num_comps kvps and keys all in one block
4070
4071             aParameters = (PvmiKvp*)oscl_malloc(num_comps * sizeof(PvmiKvp));
4072             if (aParameters == NULL)
4073             {
4074                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
4075                 return PVMFErrNoMemory;
4076             }
4077
4078             oscl_memset(aParameters, 0, num_comps*sizeof(PvmiKvp));
4079
4080             // Allocate memory for the key strings in each KVP
4081             PvmiKeyType memblock = (PvmiKeyType)oscl_malloc(num_comps * (sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) + 1) * sizeof(char));
4082             if (memblock == NULL)
4083             {
4084                 oscl_free(aParameters);
4085                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
4086                 return PVMFErrNoMemory;
4087             }
4088             oscl_strset(memblock, 0, num_comps *(sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) + 1) * sizeof(char));
4089
4090
4091             // allocate a block of memory for component names
4092             OMX_U8 *memblockomx = (OMX_U8 *) oscl_malloc(num_comps * PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
4093             if (memblockomx == NULL)
4094             {
4095                 oscl_free(aParameters);
4096                 oscl_free(memblock);
4097                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for omx component strings failed"));
4098                 return PVMFErrNoMemory;
4099             }
4100
4101             oscl_memset(memblockomx, 0, num_comps * PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8));
4102
4103             // allocate a placeholder
4104             CompOfRole = (OMX_STRING *)oscl_malloc(num_comps * sizeof(OMX_STRING));
4105
4106             for (ii = 0; ii < num_comps; ii++)
4107             {
4108                 CompOfRole[ii] = (OMX_STRING)(memblockomx + (ii * PV_OMX_MAX_COMPONENT_NAME_LENGTH * sizeof(OMX_U8)));
4109             }
4110
4111             // call 2nd time to get the component names
4112             Err = OMX_MasterGetComponentsOfRole(aInputParameters.cComponentRole, &num_comps, (OMX_U8 **)CompOfRole);
4113             if (OMX_ErrorNone == Err)
4114             {
4115                 for (ii = 0; ii < num_comps; ii++)
4116                 {
4117                     aInputParameters.cComponentName = CompOfRole[ii];
4118                     status = OMX_MasterConfigParser(&aInputParameters, &aOutputParameters);
4119                     if (status == OMX_TRUE)
4120                     {
4121                         // component passes the test - write the component name into kvp list
4122                         // write the key
4123                         aParameters[ii].key = memblock + (aNumParamElements * (sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)) + 1) * sizeof(char)) ;
4124                         oscl_strncat(aParameters[ii].key, _STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY), sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY)));
4125                         aParameters[ii].key[sizeof(_STRLIT_CHAR(PVMF_DEC_AVAILABLE_OMX_COMPONENTS_KEY))] = 0; // null terminate
4126
4127                         // write the length
4128                         aParameters[ii].length = PV_OMX_MAX_COMPONENT_NAME_LENGTH;
4129
4130                         aParameters[ii].value.pChar_value = CompOfRole[ii];
4131                         aNumParamElements++;
4132
4133                     }
4134
4135                 }
4136             }
4137
4138             // free memory for CompOfRole placeholder.
4139             // The other blocks of memory will be freed during release parameter sync
4140             oscl_free(CompOfRole);
4141         }
4142         else
4143         {
4144             // if no component supports the role, nothing else to do
4145             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "%s::PVMFOMXVideoDecNode::DoCapConfigGetParameters() No OMX components support the role", iName.Str()));
4146             return PVMFErrNotSupported;
4147         }
4148
4149
4150         return PVMFSuccess;
4151
4152
4153     }
4154     else if (pv_mime_strcmp(aIdentifier, PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY) == 0)
4155     {
4156         // set the mime type if audio format is being used
4157         PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE,
4158                         (0, "PVMFOMXAudioDecNode::DoCapConfigGetParameters() audio dec pcm buffer size is %d milliseconds", iOutputBufferPCMDuration));
4159
4160         // allocate kvp
4161         aNumParamElements = 1;
4162         aParameters = (PvmiKvp*)oscl_malloc(sizeof(PvmiKvp));
4163         if (aParameters == NULL)
4164         {
4165             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for KVP failed"));
4166             return PVMFErrNoMemory;
4167         }
4168         oscl_memset(aParameters, 0, sizeof(PvmiKvp));
4169
4170         // Allocate memory for the key strings in each KVP
4171         PvmiKeyType memblock = (PvmiKeyType)oscl_malloc((sizeof(_STRLIT_CHAR(PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY)) + 1) * sizeof(char));
4172         if (memblock == NULL)
4173         {
4174             oscl_free(aParameters);
4175             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Memory allocation for key string failed"));
4176             return PVMFErrNoMemory;
4177         }
4178         oscl_strset(memblock, 0, (sizeof(_STRLIT_CHAR(PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY)) + 1) * sizeof(char));
4179
4180         aParameters->key = memblock;
4181
4182         oscl_strncat(aParameters->key, _STRLIT_CHAR(PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY), sizeof(_STRLIT_CHAR(PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY)));
4183         aParameters->key[sizeof(_STRLIT_CHAR(PVMF_AUDIO_DEC_PCM_BUFFER_DURATION_KEY))] = 0; // null terminate
4184
4185
4186         aParameters->value.uint32_value = iOutputBufferPCMDuration;
4187
4188     }
4189
4190
4191     PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Out"));
4192     if (aNumParamElements == 0)
4193     {
4194         // If no one could get the parameter, return error
4195         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "PVMFOMXVideoDecNode::DoCapConfigGetParametersSync() Unsupported key"));
4196         return PVMFFailure;
4197     }
4198     else
4199     {
4200         return PVMFSuccess;
4201     }
4202
4203 }