• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* ------------------------------------------------------------------
2  * Copyright (C) 1998-2009 PacketVideo
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
13  * express or implied.
14  * See the License for the specific language governing permissions
15  * and limitations under the License.
16  * -------------------------------------------------------------------
17  */
18 #include "oscl_rand.h"
19 #include "logicalchannel.h"
20 #include "pvmf_simple_media_buffer.h"
21 #include "pvmf_media_data.h"
22 #include "pvmf_media_cmd.h"
23 #include "pvmf_media_msg_format_ids.h"
24 
25 #ifndef OSCL_MIME_STRING_UTILS_H
26 #include "pv_mime_string_utils.h"
27 #endif
28 
29 #ifndef PER_COPIER
30 #include "h245_copier.h"
31 #endif
32 
33 #ifndef PER_DELETER
34 #include "h245_deleter.h"
35 #endif
36 // decreasing DEF_CHANNEL_BUFFER_SIZE_MS can result out of memory errors,
37 // please change also PV_MAX_VIDEO_FRAME_SIZE to lower value.
38 #define DEF_CHANNEL_BITRATE 64000
39 #define DEF_INCOMING_CHANNEL_BUFFER_SIZE_MS 2800
40 #define DEF_OUTGOING_CHANNEL_BUFFER_SIZE_MS 2800
41 #define TIMESTAMP_MAX INT_MAX
42 #define DEF_SEGMENTABLE_CHANNEL_OH_BPS 2000
43 #define H223_INCOMING_CHANNEL_NUM_MEDIA_MSG 300
44 #define H223_OUTGOING_CHANNEL_NUM_MEDIA_MSG 300
45 #define H223_INCOMING_CHANNEL_FRAGMENT_SIZE 128
46 #define H223_INCOMING_CHANNEL_NUM_MEDIA_DATA 300
47 #define H223_INCOMING_CHANNEL_NUM_FRAGS_IN_MEDIA_DATA (3*1024/128)
48 #define PV2WAY_BPS_TO_BYTES_PER_MSEC_RIGHT_SHIFT 13
49 
50 
51 #define H223_LCN_IN_TIMESTAMP_BASE 40
52 
53 
H223LogicalChannel(TPVChannelId num,bool segmentable,OsclSharedPtr<AdaptationLayer> & al,PS_DataType data_type,LogicalChannelObserver * observer,uint32 bitrate,uint32 sample_interval,uint32 num_media_data)54 H223LogicalChannel::H223LogicalChannel(TPVChannelId num,
55                                        bool segmentable,
56                                        OsclSharedPtr<AdaptationLayer>& al,
57                                        PS_DataType data_type,
58                                        LogicalChannelObserver* observer,
59                                        uint32 bitrate,
60                                        uint32 sample_interval,
61                                        uint32 num_media_data)
62         : PvmfPortBaseImpl(num, this),
63         lcn(num),
64         next(NULL),
65         iAl(al),
66         iBitrate(0),
67         iSampleInterval(0),
68         iObserver(observer),
69         iFormatSpecificInfo(NULL),
70         iFormatSpecificInfoLen(0),
71         iLogger(NULL),
72         iDataType(NULL),
73         iAudioLatency(0),
74         iVideoLatency(0)
75 {
76     iSegmentable = segmentable;
77     iIncomingSkew = 0;
78     iLastSduTimestamp = 0;
79     iSampleInterval = sample_interval;
80     uint32 bitrate_overhead = IsSegmentable() ? DEF_SEGMENTABLE_CHANNEL_OH_BPS :
81                               (uint32)((2000 / sample_interval + 1) >> 1) * (al->GetHdrSz() + al->GetTrlrSz());
82     iBitrate = bitrate + bitrate_overhead;
83     iNumMediaData = num_media_data;
84     iMaxSduSize = (uint16)(iAl->GetSduSize() - iAl->GetHdrSz() - iAl->GetTrlrSz());
85     if (data_type)
86     {
87         iDataType = Copy_DataType(data_type);
88     }
89     iMediaType = GetFormatType();
90     iPaused = false;
91     iClock = NULL;
92 }
93 
~H223LogicalChannel()94 H223LogicalChannel::~H223LogicalChannel()
95 {
96     if (iDataType)
97     {
98         Delete_DataType(iDataType);
99         OSCL_DEFAULT_FREE(iDataType);
100         iDataType = NULL;
101     }
102     if (iFormatSpecificInfo)
103     {
104         oscl_free(iFormatSpecificInfo);
105         iFormatSpecificInfo = NULL;
106         iFormatSpecificInfoLen = 0;
107     }
108 
109 }
110 
Init()111 void H223LogicalChannel::Init()
112 {
113     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LogicalChannel::Init"));
114     iSendFormatSpecificInfo = false;
115 }
116 
SetFormatSpecificInfo(uint8 * info,uint16 info_len)117 PVMFStatus H223LogicalChannel::SetFormatSpecificInfo(uint8* info, uint16 info_len)
118 {
119     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LogicalChannel::SetFormatSpecificInfo lcn=%d, info_len=%d, info=%x", lcn, info_len, info));
120     iSendFormatSpecificInfo = false;
121     if (iFormatSpecificInfo)
122     {
123         oscl_free(iFormatSpecificInfo);
124         iFormatSpecificInfo = NULL;
125         iFormatSpecificInfoLen = 0;
126     }
127 
128     if (info == NULL || info_len == 0)
129         return PVMFSuccess;
130 
131     iFormatSpecificInfo = (uint8*)oscl_malloc(info_len);
132     oscl_memcpy(iFormatSpecificInfo, info, info_len);
133     iFormatSpecificInfoLen = info_len;
134     iSendFormatSpecificInfo = true;
135     return PVMFSuccess;
136 }
137 
GetFormatSpecificInfo(uint32 * info_len)138 const uint8* H223LogicalChannel::GetFormatSpecificInfo(uint32* info_len)
139 {
140     if (info_len == NULL)
141     {
142         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LogicalChannel::GetFormatSpecificInfo ERROR info_len==NULL"));
143         return NULL;
144     }
145     *info_len = iFormatSpecificInfoLen;
146     return iFormatSpecificInfo;
147 }
148 
149 
QueryInterface(const PVUuid & aUuid,OsclAny * & aPtr)150 OSCL_EXPORT_REF void H223LogicalChannel::QueryInterface(const PVUuid& aUuid, OsclAny*& aPtr)
151 {
152     aPtr = NULL;
153     if (aUuid == PVMI_CAPABILITY_AND_CONFIG_PVUUID)
154     {
155         aPtr = (PvmiCapabilityAndConfig*)this;
156     }
157     else if (aUuid == PVH324MLogicalChannelInfoUuid)
158     {
159         aPtr = (LogicalChannelInfo*)this;
160     }
161     else
162     {
163         OSCL_LEAVE(OsclErrNotSupported);
164     }
165 }
166 
Pause()167 void H223LogicalChannel::Pause()
168 {
169     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Pause lcn=%d", lcn));
170     iPaused = true;
171     // flush any pending media data
172     Flush();
173 }
174 
Resume()175 void H223LogicalChannel::Resume()
176 {
177     iPaused = false;
178 }
179 
H223OutgoingChannel(TPVChannelId num,bool segmentable,OsclSharedPtr<AdaptationLayer> & al,PS_DataType data_type,LogicalChannelObserver * observer,uint32 bitrate,uint32 sample_interval,uint32 num_media_data)180 H223OutgoingChannel::H223OutgoingChannel(TPVChannelId num,
181         bool segmentable,
182         OsclSharedPtr<AdaptationLayer>& al,
183         PS_DataType data_type,
184         LogicalChannelObserver* observer,
185         uint32 bitrate,
186         uint32 sample_interval,
187         uint32 num_media_data)
188         : H223LogicalChannel(num, segmentable, al, data_type, observer, bitrate, sample_interval, num_media_data),
189         iMediaMsgMemoryPool(NULL),
190         iMediaDataEntryAlloc(NULL),
191         iMediaFragGroupAlloc(NULL),
192         iPduPktMemPool(NULL)
193 {
194     iLogger = PVLogger::GetLoggerObject("3g324m.h223.H223OutgoingChannel");
195     iOutgoingVideoLogger = PVLogger::GetLoggerObject("datapath.outgoing.video.h223.lcn");
196     iOutgoingAudioLogger = PVLogger::GetLoggerObject("datapath.outgoing.audio.h223.lcn");
197 
198     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::H223OutgoingChannel - num(%d),segmentable(%d)", num, segmentable));
199     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::H223OutgoingChannel - AL SDU size(%d), hdr(%d), trlr(%d)", iAl->GetSduSize(), iAl->GetHdrSz(), iAl->GetTrlrSz()));
200     ResetStats();
201     lastMediaData = NULL;
202 
203     iSetBufferMediaMs = 0;
204     iSetBufferMediaBytes = 0;
205     iBufferMediaMs = 0;
206     iBufferMediaBytes = 0;
207     iCurPduTimestamp = 0;
208     iNumPendingPdus = 0;
209     iMuxingStarted = false;
210     iWaitForRandomAccessPoint = false;
211     iBufferSizeMs = DEF_OUTGOING_CHANNEL_BUFFER_SIZE_MS;
212 
213 }
214 
~H223OutgoingChannel()215 H223OutgoingChannel::~H223OutgoingChannel()
216 {
217     if (iDataType)
218     {
219         Delete_DataType(iDataType);
220         OSCL_DEFAULT_FREE(iDataType);
221         iDataType = NULL;
222     }
223     Flush();
224     iMediaFragGroupAlloc->removeRef();
225     OSCL_DELETE(iPduPktMemPool);
226     OSCL_DELETE(iMediaDataEntryAlloc);
227     OSCL_DELETE(iMediaMsgMemoryPool);
228 
229 }
230 
Init()231 void H223OutgoingChannel::Init()
232 {
233     H223LogicalChannel::Init();
234     iMediaMsgMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (H223_OUTGOING_CHANNEL_NUM_MEDIA_MSG));
235     iMediaMsgMemoryPool->enablenullpointerreturn();
236     iMediaDataEntryAlloc = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (iNumMediaData, sizeof(LCMediaDataEntry)));
237     iMediaDataEntryAlloc->enablenullpointerreturn();
238     iPduPktMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (iNumMediaData));
239     iPduPktMemPool->enablenullpointerreturn();
240     iMediaFragGroupAlloc = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>, (iNumMediaData, 10, iPduPktMemPool));
241     iMediaFragGroupAlloc->create();
242 }
243 
244 
BufferMedia(uint16 aMs)245 void H223OutgoingChannel::BufferMedia(uint16 aMs)
246 {
247     if (iBufferSizeMs && aMs > iBufferSizeMs)
248     {
249         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::BufferMedia ERROR buffer interval=%d > buffer size=%d", aMs, iBufferSizeMs));
250     }
251     iSetBufferMediaMs = iBufferMediaMs = aMs;
252     iSetBufferMediaBytes = iBufferMediaBytes = ((iBufferSizeMs * iBitrate + 4000) / 8000);
253     //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"H223OutgoingChannel::BufferMedia ms=%d,bytes=%d", iBufferMediaMs,iBufferMediaBytes));
254 }
255 
Resume()256 void H223OutgoingChannel::Resume()
257 {
258     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Resume lcn=%d", lcn));
259     H223LogicalChannel::Resume();
260     iPaused = false;
261     // start muxing on a random access point
262     //iWaitForRandomAccessPoint=true;
263 }
264 
SetBufferSizeMs(uint32 buffer_size_ms)265 void H223OutgoingChannel::SetBufferSizeMs(uint32 buffer_size_ms)
266 {
267     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingLogicalChannel::SetBufferSizeMs buffer_size_ms=%d", buffer_size_ms));
268     iBufferSizeMs = buffer_size_ms;
269 }
270 
271 
272 
PutData(PVMFSharedMediaMsgPtr media_msg)273 PVMFStatus H223OutgoingChannel::PutData(PVMFSharedMediaMsgPtr media_msg)
274 {
275     PVMFStatus ret = PVMFSuccess;
276     PVMFSharedMediaDataPtr mediaData;
277     convertToPVMFMediaData(mediaData, media_msg);
278 
279     PV_STAT_SET_TIME(iStartTime, iNumPacketsIn)
280     PV_STAT_INCR(iNumPacketsIn, 1)
281 
282     /* zero through 255 is reserved for media data */
283     if (media_msg->getFormatID() >= PVMF_MEDIA_CMD_FORMAT_IDS_START)
284     {
285         return PVMFSuccess;
286     }
287 
288     PV_STAT_INCR(iNumBytesIn, (mediaData->getFilledSize()))
289     TimeValue timenow;
290     if (iMediaType.isCompressed() && iMediaType.isAudio())
291     {
292         PVMF_OUTGOING_AUDIO_LOGDATATRAFFIC((0, "Outgoing audio frames received. Stats: Entry time=%ud, lcn=%d, size=%d", timenow.to_msec(), lcn, mediaData->getFilledSize()));
293     }
294     else if (iMediaType.isCompressed() && iMediaType.isVideo())
295     {
296         PVMF_OUTGOING_VIDEO_LOGDATATRAFFIC((0, "Outgoing video frames received.Stats: Entry time=%ud, lcn=%d, size=%d", timenow.to_msec(), lcn, mediaData->getFilledSize()));
297     }
298 
299     if (iNumPacketsIn % 20 == 0)
300     {
301         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData lcn=%d, size=%d, ts=%d", lcn, mediaData->getFilledSize(), mediaData->getTimestamp()));
302     }
303 
304     // Check for FormatSpecificInfo.  Sending FSI with data is being obsoleted, but there is no harm in leaving this in for now.
305     if (mediaData->getFormatSpecificInfo(iFsiFrag) && iFsiFrag.getMemFragPtr() && iFsiFrag.getMemFragSize())
306     {
307         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData Received Format Specific Info, len=%d", iFsiFrag.getMemFragSize()));
308         iObserver->ReceivedFormatSpecificInfo(lcn, (uint8*)iFsiFrag.getMemFragPtr(), iFsiFrag.getMemFragSize());
309     }
310 
311     if (IsSegmentable() && iWaitForRandomAccessPoint)
312     {
313         if ((mediaData->getMarkerInfo()&PVMF_MEDIA_DATA_MARKER_INFO_RANDOM_ACCESS_POINT_BIT) == 0)
314         {
315             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData Not random access point.  Dropping media data."));
316             return PVMFErrInvalidState;
317         }
318         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData Found random access point."));
319         iWaitForRandomAccessPoint = false;
320     }
321     else if (iNumPendingPdus == (iNumMediaData - 1))
322     {
323         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData - ERROR Overflow, iNumPendingPdus=%d", iNumPendingPdus));
324         return PVMFErrOverflow;
325     }
326 
327     uint32 num_frags_required = 0;
328     uint32 frag_num = 0;
329     for (frag_num = 0; frag_num < mediaData->getNumFragments(); frag_num++)
330     {
331         OsclRefCounterMemFrag memfrag;
332         mediaData->getMediaFragment(frag_num, memfrag);
333         if (memfrag.getMemFragSize() > iMaxSduSize)
334         {
335             num_frags_required++;
336         }
337     }
338 
339     if ((mediaData->getNumFragments() + num_frags_required + iNumPendingPdus) >= (iNumMediaData - 1))
340     {
341         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData - ERROR Overflow, iNumPendingPdus=%d, num_frags_required=%d,iNumMediaData=%d", iNumPendingPdus, num_frags_required, iNumMediaData));
342         Flush();
343         /* Start re-buffering */
344         BufferMedia((uint16)iSetBufferMediaMs);
345         return PVMFErrOverflow;
346     }
347 
348     /* Fragment the sdu if needed */
349     PVMFSharedMediaDataPtr& fragmentedMediaData = mediaData;
350     if (num_frags_required)
351     {
352         if (true != FragmentPacket(mediaData, fragmentedMediaData))
353         {
354             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData - Memory allocation failure on Fragment\n"));
355             return PVMFErrOverflow;
356         }
357     }
358 
359     uint32 sdu_size = 0;
360     if (iCurPdu.GetRep())
361     {
362         sdu_size = iCurPdu->getFilledSize() - iAl->GetHdrSz();
363         /* Is the timestamp different ? */
364         if (iCurPduTimestamp != fragmentedMediaData->getTimestamp() || !IsSegmentable())
365         {
366             if (PVMFSuccess != CompletePdu())
367             {
368                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData - Memory allocation failure on CompletePdu\n"));
369                 return PVMFErrOverflow;
370             }
371             sdu_size = 0;
372         }
373     }
374     if (sdu_size == 0)
375     {
376         //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"H223OutgoingChannel::PutData Sdu size == 0"));
377         iCurPdu = StartAlPdu();
378         if (!iCurPdu)
379         {
380             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
381                             (0, "H223OutgoingChannel::PutData - Memory allocation failure on StartAlPdu\n"));
382             return PVMFErrOverflow;
383         }
384 
385         if (iFsiFrag.getMemFragSize())
386         {
387             iCurPdu->appendMediaFragment(iFsiFrag);
388             // reset the FSI frag
389             OsclRefCounterMemFrag frag;
390             iFsiFrag = frag;
391         }
392     }
393 
394     for (frag_num = 0; frag_num < fragmentedMediaData->getNumFragments(); frag_num++)
395     {
396         OsclRefCounterMemFrag frag;
397         fragmentedMediaData->getMediaFragment(frag_num, frag);
398         OSCL_ASSERT(frag.getMemFragSize() <= iMaxSduSize);
399 
400         if (sdu_size &&
401                 ((sdu_size + frag.getMemFragSize() > iMaxSduSize) || !IsSegmentable()))
402         {
403             if (PVMFSuccess != CompletePdu())
404             {
405                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PutData - Memory allocation failure on CompletePdu\n"));
406                 return PVMFErrOverflow;
407             }
408             sdu_size = 0;
409 
410             iCurPdu = StartAlPdu();
411 
412             if (!iCurPdu)
413             {
414                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE,
415                                 (0, "H223OutgoingChannel::PutData - Memory allocation failure on StartAlPdu\n"));
416                 return PVMFErrOverflow;
417             }
418         }
419 
420         iCurPdu->appendMediaFragment(frag);
421         sdu_size += frag.getMemFragSize();
422         iCurPduTimestamp = fragmentedMediaData->getTimestamp();
423 
424     }
425 
426     if (iMediaType.isCompressed() && iMediaType.isAudio())
427     {
428         PVMF_OUTGOING_AUDIO_LOGDATATRAFFIC((0, "Stats of the outgoing audio SDU are: timestamp=%d, size=%d", iCurPduTimestamp, sdu_size));
429     }
430     else if (iMediaType.isCompressed() && iMediaType.isVideo())
431     {
432         PVMF_OUTGOING_VIDEO_LOGDATATRAFFIC((0, "Stats of the outgoing video SDU are: timestamp=%d, size=%d", iCurPduTimestamp, sdu_size));
433     }
434     return ret;
435 }
436 
FragmentPacket(PVMFSharedMediaDataPtr & aMediaData,PVMFSharedMediaDataPtr & aFragmentedMediaData)437 bool H223OutgoingChannel::FragmentPacket(PVMFSharedMediaDataPtr& aMediaData, PVMFSharedMediaDataPtr& aFragmentedMediaData)
438 {
439     OsclRefCounterMemFrag memfrag;
440     OsclSharedPtr<PVMFMediaDataImpl> newpack;
441     newpack = iMediaFragGroupAlloc->allocate();
442     if (!newpack.GetRep())
443     {
444         return false;
445     }
446 
447     int32 pkt_size = 0;
448     PVMFTimestamp timestamp = aMediaData->getTimestamp();
449     for (uint32 frag_num = 0; frag_num < aMediaData->getNumFragments(); frag_num++)
450     {
451         aMediaData->getMediaFragment(frag_num, memfrag);
452         pkt_size = memfrag.getMemFragSize();
453         if ((unsigned)pkt_size <= iMaxSduSize)
454         {
455             newpack->appendMediaFragment(memfrag);
456         }
457         else  /* Need to fragment it */
458         {
459             uint8* pos = (uint8*)memfrag.getMemFragPtr();
460             int32 trim_frag_sz = iMaxSduSize;
461             while (pkt_size)
462             {
463                 trim_frag_sz = ((unsigned)pkt_size > iMaxSduSize) ? iMaxSduSize : pkt_size;
464                 pkt_size -= trim_frag_sz;
465                 OsclRefCounterMemFrag trim_frag(memfrag);
466                 trim_frag.getMemFrag().ptr = pos;
467                 trim_frag.getMemFrag().len = trim_frag_sz;
468                 newpack->appendMediaFragment(trim_frag);
469                 pos += trim_frag_sz;
470             }
471         }
472     }
473     aFragmentedMediaData = PVMFMediaData::createMediaData(newpack, iMediaMsgMemoryPool);
474     if (aFragmentedMediaData.GetRep())
475     {
476         aFragmentedMediaData->setTimestamp(timestamp);
477         return true;
478     }
479     return false;
480 }
481 
StartAlPdu()482 OsclSharedPtr<PVMFMediaDataImpl> H223OutgoingChannel::StartAlPdu()
483 {
484     PV_STAT_INCR(iNumSdusIn, 1)
485 
486     // allocate packet
487     OsclSharedPtr<PVMFMediaDataImpl> pdu = iMediaFragGroupAlloc->allocate();
488     if (pdu)
489     {
490         // Add header
491         PVMFStatus status = iAl->StartPacket(pdu);
492         if (status != PVMFSuccess)
493         {
494             pdu.Unbind();
495             return pdu;
496         }
497         iNumPendingPdus++;
498     }
499 
500     return pdu;
501 }
502 
CompletePdu()503 PVMFStatus H223OutgoingChannel::CompletePdu()
504 {
505     PVMFStatus status = iAl->CompletePacket(iCurPdu);
506     if (status != PVMFSuccess)
507     {
508         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::CompletePdu Memory allocation failedlcn=%d, CompletePacket status=%d", lcn, status));
509         return status;
510     }
511     // Add it to the outgoing queue
512     status = AppendOutgoingPkt(iCurPdu, iCurPduTimestamp);
513     if (status != PVMFSuccess)
514     {
515         return status;
516     }
517     iCurPdu.Unbind();
518     iCurPduTimestamp = 0;
519     return PVMFSuccess;
520 }
521 
AppendOutgoingPkt(OsclSharedPtr<PVMFMediaDataImpl> & pdu,PVMFTimestamp timestamp,OsclRefCounterMemFrag * fsi)522 PVMFStatus H223OutgoingChannel::AppendOutgoingPkt(OsclSharedPtr<PVMFMediaDataImpl>& pdu,
523         PVMFTimestamp timestamp,
524         OsclRefCounterMemFrag* fsi)
525 {
526     PVMFSharedMediaDataPtr mediaData = PVMFMediaData::createMediaData(pdu, iMediaMsgMemoryPool);
527     if (mediaData.GetRep() == NULL)
528     {
529         return PVMFErrNoMemory;
530     }
531 
532     mediaData->setTimestamp(timestamp);
533     if (fsi)
534     {
535         mediaData->setFormatSpecificInfo(*fsi);
536     }
537     void* memory_for_entry = iMediaDataEntryAlloc->allocate(sizeof(LCMediaDataEntry));
538     if (!memory_for_entry)
539     {
540         // if couldn't allocate memory - leave
541         return PVMFErrNoMemory;
542     }
543     LCMediaDataEntry* entry = new(memory_for_entry) LCMediaDataEntry();
544     entry->mediaData = mediaData;
545 
546     LCMediaDataEntry* first = entry;
547     PVMFTimestamp lastTS = timestamp;
548     if (lastMediaData)
549     {
550         first = lastMediaData->next;
551         lastMediaData->next = entry;
552         lastTS = lastMediaData->mediaData->getTimestamp();
553     }
554     lastMediaData = entry;
555     entry->next = first;
556 
557     /* Adjust buffering parameters */
558     if (iBufferMediaMs)
559     {
560         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::AppendOutgoingPkt lcn=%d, last ts=%d,cur ts=%d", lcn, lastTS, timestamp));
561         /* Compute delta_t from last media data */
562         int32 delta_t = timestamp - lastTS;
563         if (delta_t < 0)
564             delta_t += TIMESTAMP_MAX;
565         iBufferMediaMs -= delta_t;
566         iBufferMediaBytes -= mediaData->getFilledSize();
567         if (iBufferMediaMs <= 0 || iBufferMediaBytes <= 0)
568         {
569             iBufferMediaMs = 0;
570             iBufferMediaBytes = 0;
571         }
572     }
573     return PVMFSuccess;
574 }
575 
GetNextPacket(PVMFSharedMediaDataPtr & aMediaData,PVMFStatus aStatus)576 bool H223OutgoingChannel::GetNextPacket(PVMFSharedMediaDataPtr& aMediaData, PVMFStatus aStatus)
577 {
578     if (!iMuxingStarted && aStatus == PVMFSuccess)
579         iMuxingStarted = true;
580 
581     if (lastMediaData == NULL)
582     {
583         return false;
584     }
585     if ((aStatus == PVMFSuccess) && iPaused)
586     {
587         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::GetNextPacket Logical channel %d paused.", lcn));
588         return false;
589 
590     }
591     if ((aStatus == PVMFSuccess) && iBufferMediaMs && iBufferMediaBytes)
592     {
593         /* Still buffering */
594         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::GetNextPacket Buffering lcn=%d, ms left=%d", lcn, iBufferMediaMs));
595         return false;
596     }
597 
598     LCMediaDataEntry* first = lastMediaData->next;
599     aMediaData = first->mediaData;
600 
601     if (first == lastMediaData)
602     {
603         lastMediaData = NULL;
604     }
605     else
606     {
607         lastMediaData->next = first->next;
608     }
609     first->~LCMediaDataEntry();
610     iMediaDataEntryAlloc->deallocate(first);
611 
612     iNumPendingPdus--;
613     return true;
614 }
615 
ReleasePacket(PVMFSharedMediaDataPtr & aMediaData)616 OsclAny H223OutgoingChannel::ReleasePacket(PVMFSharedMediaDataPtr& aMediaData)
617 {
618     OsclSharedPtr<PVMFMediaDataImpl> aMediaDataImpl;
619     aMediaData->getMediaDataImpl(aMediaDataImpl);
620     aMediaDataImpl->clearMediaFragments();
621 }
622 
Flush()623 OsclAny H223OutgoingChannel::Flush()
624 {
625     //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"H223OutgoingChannel::Flush\n"));
626 
627     PVMFSharedMediaDataPtr aMediaData;
628     // clear messages in input queue
629     ClearMsgQueues();
630     // go through pending queue
631     while (GetNextPacket(aMediaData, PVMFErrCancelled))
632     {
633         PV_STAT_INCR(iNumBytesFlushed, aMediaData->getFilledSize())
634         OsclSharedPtr<PVMFMediaDataImpl> aMediaDataImpl;
635         aMediaData->getMediaDataImpl(aMediaDataImpl);
636         aMediaDataImpl->clearMediaFragments();
637     }
638     if (iCurPdu.GetRep())
639     {
640         iCurPdu->clearMediaFragments();
641         iCurPdu.Unbind();
642     }
643     iCurPduTimestamp = 0;
644     iNumPendingPdus = 0;
645 }
ResetStats()646 OsclAny H223OutgoingChannel::ResetStats()
647 {
648     iNumPacketsIn = 0;
649     iNumSdusIn = 0;
650     iNumBytesIn = 0;
651     iNumSdusDropped = 0;
652     iNumSdusOut = 0;
653     iNumBytesOut = 0;
654     iMaxPacketMuxTime = 0;
655     iMaxSduMuxTime = 0;
656     iNumFlush = 0;
657     iNumBytesFlushed = 0;
658 }
659 
LogStats()660 OsclAny H223OutgoingChannel::LogStats()
661 {
662     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Outgoing Logical Channel %d Statistics:\n", lcn));
663     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Adaptation layer header bytes -  %d\n", iAl->GetHdrSz()));
664     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Adaptation layer trailer bytes -  %d\n", iAl->GetTrlrSz()));
665     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num packets received - %d\n", iNumPacketsIn));
666     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus received - %d\n", iNumSdusIn));
667     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes received - %d\n", iNumBytesIn));
668     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus dropped - %d\n", iNumSdusDropped));
669     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus output - %d\n", iNumSdusOut));
670     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes output - %d\n", iNumBytesOut));
671     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Max packet mux time - %d\n", iMaxPacketMuxTime));
672     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Max sdu mux time - %d\n", iMaxSduMuxTime));
673     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num flush - %d\n", iNumFlush));
674     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes flushed - %d\n", iNumBytesFlushed));
675 }
676 
Connect(PVMFPortInterface * aPort)677 OSCL_EXPORT_REF PVMFStatus H223OutgoingChannel::Connect(PVMFPortInterface* aPort)
678 {
679     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Connect, aPort=%x", aPort));
680 
681     if (iConnectedPort)
682     {
683         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Connect Error: Already connected"));
684         return PVMFFailure;
685     }
686 
687     PvmiCapabilityAndConfig* config = NULL;
688     OsclAny* tempInterface = NULL;
689     aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, tempInterface);
690     config = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, tempInterface);
691     if (!config)
692     {
693         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Connect: Error - Peer port does not support capability interface"));
694         return PVMFFailure;
695     }
696 
697     PVMFStatus status = NegotiateInputSettings(config);
698 
699     if (status != PVMFSuccess)
700     {
701         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Connect: Error - Settings negotiation failed. status=%d", status));
702         return status;
703     }
704 
705     //Automatically connect the peer.
706     if ((status = aPort->PeerConnect(this)) != PVMFSuccess)
707     {
708         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::Connect: Error - Peer Connect failed. status=%d", status));
709         return status;
710     }
711 
712     iConnectedPort = aPort;
713 
714     PortActivity(PVMF_PORT_ACTIVITY_CONNECT);
715     return PVMFSuccess;
716 }
PeerConnect(PVMFPortInterface * aPort)717 OSCL_EXPORT_REF PVMFStatus H223OutgoingChannel::PeerConnect(PVMFPortInterface* aPort)
718 {
719 
720     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::PeerConnect aPort=0x%x", this, aPort));
721     if (!aPort)
722     {
723         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "0x%x H223OutgoingChannel::PeerConnect: Error - Connecting to invalid port", this));
724         return PVMFErrArgument;
725     }
726     if (iConnectedPort)
727     {
728         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "0x%x H223OutgoingChannel::PeerConnect: Error - Already connected", this));
729         return PVMFFailure;
730     }
731 
732     OsclAny* config = NULL;
733     aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, config);
734     if (!config)
735     {
736         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::PeerConnect: Error - Peer port does not support capability interface"));
737         return PVMFFailure;
738     }
739 
740 
741     PVMFStatus status = PVMFSuccess;
742 
743     status = NegotiateInputSettings((PvmiCapabilityAndConfig*)config);
744 
745     if (status != PVMFSuccess)
746     {
747         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::PeerConnect: Error - Settings negotiation failed. status=%d", status));
748         return status;
749     }
750 
751 
752     iConnectedPort = aPort;
753     PortActivity(PVMF_PORT_ACTIVITY_CONNECT);
754 
755     return status;
756 }
757 
NegotiateFSISettings(PvmiCapabilityAndConfig * aConfig)758 PVMFStatus H223OutgoingChannel::NegotiateFSISettings(PvmiCapabilityAndConfig* aConfig)
759 {
760     PvmiKvp* kvp = NULL;
761     int numParams = 0;
762 
763     // Preconfigured FSI
764     uint8* pc_fsi = NULL;
765     unsigned pc_fsilen = ::GetFormatSpecificInfo(iDataType, pc_fsi);
766     if (pc_fsilen && pc_fsi)
767     {
768         /*
769          * Create PvmiKvp for capability settings
770          */
771         OsclMemAllocator alloc;
772         PvmiKvp kvp;
773         kvp.key = NULL;
774         kvp.length = oscl_strlen(PVMF_FORMAT_SPECIFIC_INFO_KEY) + 1; // +1 for \0
775         kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
776         if (kvp.key == NULL)
777         {
778             return PVMFFailure;
779         }
780         oscl_strncpy(kvp.key, PVMF_FORMAT_SPECIFIC_INFO_KEY, kvp.length);
781 
782         kvp.value.key_specific_value = (OsclAny*)pc_fsi;
783         kvp.capacity = pc_fsilen;
784         kvp.length = pc_fsilen;
785 
786         PvmiKvp* retKvp = NULL; // for return value
787         int32 err;
788         OSCL_TRY(err, aConfig->setParametersSync(NULL, &kvp, 1, retKvp););
789         alloc.deallocate((OsclAny*)(kvp.key));
790         if (err)
791         {
792             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::NegotiateFSISettings, Failed to set FSI on peer, err=%d", err));
793         }
794         return err;
795     }
796 
797 
798     // No preconfigured FSI.  In this case try to get the FSI from the peer.
799     PVMFStatus status = aConfig->getParametersSync(NULL, (PvmiKeyType)PVMF_FORMAT_SPECIFIC_INFO_KEY, kvp, numParams, NULL);
800     if (status != PVMFSuccess || numParams != 1)
801     {
802         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateFSISettings: Failed to get FSI from peer"));
803         return PVMFSuccess;
804     }
805     else
806     {
807         ReceivedFSIFromPeer(kvp);
808         aConfig->releaseParameters(NULL, kvp, numParams);
809     }
810 
811     kvp = NULL;
812     numParams = 0;
813     return PVMFSuccess;
814 
815 }
816 
ReceivedFSIFromPeer(PvmiKvp * kvp)817 PVMFStatus H223OutgoingChannel::ReceivedFSIFromPeer(PvmiKvp* kvp)
818 {
819     // Create mem frag for VOL header
820     OsclRefCounter* my_refcnt;
821     OsclMemAllocDestructDealloc<uint8> my_alloc;
822     uint aligned_refcnt_size = oscl_mem_aligned_size(sizeof(OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >));
823     uint8* my_ptr = (uint8*) my_alloc.allocate(aligned_refcnt_size + kvp->length);
824     my_refcnt = OSCL_PLACEMENT_NEW(my_ptr, OsclRefCounterSA< OsclMemAllocDestructDealloc<uint8> >(my_ptr));
825     my_ptr += aligned_refcnt_size;
826 
827     oscl_memcpy(my_ptr, kvp->value.key_specific_value, kvp->length);
828 
829     OsclMemoryFragment memfrag;
830     memfrag.len = kvp->length;
831     memfrag.ptr = my_ptr;
832 
833     OsclRefCounterMemFrag configinfo(memfrag, my_refcnt, kvp->length);
834     iFsiFrag = configinfo;
835 
836     SetFormatSpecificInfo((uint8*)kvp->value.key_specific_value, kvp->length);
837 
838     iObserver->ReceivedFormatSpecificInfo(lcn, (uint8*)kvp->value.key_specific_value, kvp->length);
839     return PVMFSuccess;
840 }
841 
842 
NegotiateInputSettings(PvmiCapabilityAndConfig * aConfig)843 PVMFStatus H223OutgoingChannel::NegotiateInputSettings(PvmiCapabilityAndConfig* aConfig)
844 {
845     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::NegotiateInputSettings, aConfig=%x", aConfig));
846 
847     PvmiKvp* kvp = NULL;
848     int numParams = 0;
849     int32 i = 0;
850 
851     // Get supported output formats from peer
852     PVMFStatus status = aConfig->getParametersSync(NULL,
853                         OSCL_CONST_CAST(char*, OUTPUT_FORMATS_CAP_QUERY),
854                         kvp, numParams, NULL);
855     if (status != PVMFSuccess || numParams == 0)
856     {
857         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings, Error:  getParametersSync failed.  status=%d", status));
858         return status;
859     }
860 
861     PvmiKvp* selectedKvp = NULL;
862     PVCodecType_t codec_type = GetCodecType(iDataType);
863     PVMFFormatType lcn_format_type = PVCodecTypeToPVMFFormatType(codec_type);
864 
865     for (i = 0; i < numParams && !selectedKvp; i++)
866     {
867         if (lcn_format_type == kvp[i].value.pChar_value)
868             selectedKvp = &(kvp[i]);
869     }
870 
871     if (!selectedKvp)
872     {
873         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings, Error:  Input format not supported by peer"));
874         return PVMFFailure;
875     }
876     if (PVMFSuccess != setConfigParametersSync(selectedKvp, aConfig))
877     {
878         return PVMFFailure;
879     }
880 
881     aConfig->releaseParameters(NULL, kvp, numParams);
882     kvp = NULL;
883     numParams = 0;
884 
885 
886     if (iMediaType.isVideo())
887     {
888         // frame width negotiations
889         uint32 width = GetVideoFrameSize(iDataType, true);
890         status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_WIDTH_CAP_QUERY, kvp, numParams, NULL);
891         if (status != PVMFSuccess || numParams != 1)
892         {
893             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings: Error - config->getParametersSync(cap width) failed"));
894             // do not report error for now as enc nodes dont implemlement some parameters
895 
896         }
897         else
898         {
899             if (kvp[0].value.uint32_value > width)
900             {
901                 OsclMemAllocator alloc;
902                 PvmiKvp kvp;
903                 kvp.key = NULL;
904                 kvp.length = oscl_strlen(VIDEO_OUTPUT_WIDTH_CUR_QUERY) + 1; // +1 for \0
905                 kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
906                 if (kvp.key == NULL)
907                 {
908                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings: Error - alloc failed for VIDEO_OUTPUT_WIDTH_CUR_QUERY kvp "));
909                     return PVMFErrNoMemory;
910                 }
911                 oscl_strncpy(kvp.key, VIDEO_OUTPUT_WIDTH_CUR_QUERY, kvp.length);
912                 kvp.value.uint32_value = width;
913 
914                 if (PVMFSuccess != setConfigParametersSync(&kvp, aConfig))
915                 {
916                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings, Error:  setConfigParametersSync width failed"));
917                     //dont return PVMFFailure for now ;
918                 }
919 
920 
921                 alloc.deallocate((OsclAny*)(kvp.key));
922 
923             }
924             aConfig->releaseParameters(NULL, kvp, numParams);
925         }
926 
927         kvp = NULL;
928         numParams = 0;
929 
930 
931 
932         // frame height negotiations
933         uint32 height = GetVideoFrameSize(iDataType, false);
934         status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_HEIGHT_CAP_QUERY, kvp, numParams, NULL);
935         if (status != PVMFSuccess || numParams != 1)
936         {
937             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings: Error - config->getParametersSync(cap height) failed"));
938             // do not report error for now as enc nodes dont implemlement some parameters
939 
940         }
941         else
942         {
943             if (kvp[0].value.uint32_value > height)
944             {
945                 OsclMemAllocator alloc;
946                 PvmiKvp kvp;
947                 kvp.key = NULL;
948                 kvp.length = oscl_strlen(VIDEO_OUTPUT_HEIGHT_CUR_QUERY) + 1; // +1 for \0
949                 kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
950                 if (kvp.key == NULL)
951                 {
952                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings: Error - alloc failed for VIDEO_OUTPUT_HEIGHT_CUR_QUERY kvp "));
953                     return PVMFErrNoMemory;
954                 }
955                 oscl_strncpy(kvp.key, VIDEO_OUTPUT_HEIGHT_CUR_QUERY, kvp.length);
956                 kvp.value.uint32_value = height;
957 
958                 if (PVMFSuccess != setConfigParametersSync(&kvp, aConfig))
959                 {
960                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings, Error:  setConfigParametersSync height failed"));
961                     //dont return PVMFFailure for now;
962                 }
963                 alloc.deallocate((OsclAny*)(kvp.key));
964 
965             }
966             aConfig->releaseParameters(NULL, kvp, numParams);
967         }
968 
969         kvp = NULL;
970         numParams = 0;
971 
972         // frame rate negotiations
973         uint32 framerate = GetMaxFrameRate(iDataType);
974         // VIDEO_OUTPUT_FRAME_RATE_CAP_QUERY not available
975         status = aConfig->getParametersSync(NULL, (PvmiKeyType)VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY, kvp, numParams, NULL);
976         if (status != PVMFSuccess || numParams != 1)
977         {
978             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings: Error - config->getParametersSync(cap frame rate failed"));
979             // do not report error for now as enc nodes dont implemlement some parameters
980 
981         }
982         else
983         {
984             if (kvp[0].value.float_value > framerate)
985             {
986                 OsclMemAllocator alloc;
987                 PvmiKvp kvp;
988                 kvp.key = NULL;
989                 kvp.length = oscl_strlen(VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY) + 1; // +1 for \0
990                 kvp.key = (PvmiKeyType)alloc.ALLOCATE(kvp.length);
991                 if (kvp.key == NULL)
992                 {
993                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings: Error - alloc failed for VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY kvp "));
994                     return PVMFErrNoMemory;
995                 }
996                 oscl_strncpy(kvp.key, VIDEO_OUTPUT_FRAME_RATE_CUR_QUERY, kvp.length);
997                 kvp.value.float_value = (float)framerate;
998 
999                 if (PVMFSuccess != setConfigParametersSync(&kvp, aConfig))
1000                 {
1001                     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "H223OutgoingChannel::NegotiateInputSettings, Error:  setConfigParametersSync frame rate failed"));
1002                     //dont return PVMFFailure for now ;
1003                 }
1004                 alloc.deallocate((OsclAny*)(kvp.key));
1005 
1006             }
1007             aConfig->releaseParameters(NULL, kvp, numParams);
1008         }
1009 
1010         kvp = NULL;
1011         numParams = 0;
1012     }
1013 
1014     return NegotiateFSISettings(aConfig);
1015 }
1016 ////////////////////////////////////////////////////////////////////////////
1017 //                  PvmiCapabilityAndConfig
1018 ////////////////////////////////////////////////////////////////////////////
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)1019 OSCL_EXPORT_REF void H223OutgoingChannel::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
1020 {
1021     // Not supported
1022     OSCL_UNUSED_ARG(aObserver);
1023     OSCL_LEAVE(OsclErrNotSupported);
1024 }
1025 
1026 ////////////////////////////////////////////////////////////////////////////
getParametersSync(PvmiMIOSession session,PvmiKeyType identifier,PvmiKvp * & parameters,int & num_parameter_elements,PvmiCapabilityContext context)1027 OSCL_EXPORT_REF PVMFStatus H223OutgoingChannel::getParametersSync(PvmiMIOSession session,
1028         PvmiKeyType identifier,
1029         PvmiKvp*& parameters,
1030         int& num_parameter_elements,
1031         PvmiCapabilityContext context)
1032 {
1033     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::getParametersSync"));
1034     OSCL_UNUSED_ARG(session);
1035     OSCL_UNUSED_ARG(context);
1036 
1037     parameters = NULL;
1038     num_parameter_elements = 0;
1039 
1040     if (pv_mime_strcmp(identifier, INPUT_FORMATS_CAP_QUERY) == 0)
1041     {
1042         num_parameter_elements = 1;
1043         PVMFStatus status = AllocateKvp(iKvpMemAlloc, parameters,
1044                                         OSCL_CONST_CAST(char*, INPUT_FORMATS_VALTYPE),
1045                                         num_parameter_elements);
1046         if (status != PVMFSuccess)
1047         {
1048             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::getParametersSync: Error - AllocateKvp failed. status=%d", status));
1049             return status;
1050         }
1051         PVCodecType_t codec_type = GetCodecType(iDataType);
1052 
1053         PVMFFormatType format = PVCodecTypeToPVMFFormatType(codec_type).getMIMEStrPtr();
1054         if (format == PVMF_MIME_AMR_IF2)
1055             parameters[0].value.pChar_value = (char*) PVMF_MIME_AMR_IF2;
1056         else if (format == PVMF_MIME_PCM16)
1057             parameters[0].value.pChar_value = (char*) PVMF_MIME_PCM16;
1058         else if (format ==  PVMF_MIME_YUV420)
1059             parameters[0].value.pChar_value = (char*) PVMF_MIME_YUV420;
1060         else if (format ==  PVMF_MIME_M4V)
1061             parameters[0].value.pChar_value = (char*) PVMF_MIME_M4V;
1062         else if (format ==  PVMF_MIME_H2632000)
1063             parameters[0].value.pChar_value = (char*) PVMF_MIME_H2632000;
1064         else if (format ==  PVMF_MIME_H2631998)
1065             parameters[0].value.pChar_value = (char*) PVMF_MIME_H2631998;
1066         else
1067             parameters[0].value.pChar_value = (char*) PVMF_MIME_FORMAT_UNKNOWN;
1068     }
1069 
1070     return PVMFSuccess;
1071 }
1072 
1073 ////////////////////////////////////////////////////////////////////////////
releaseParameters(PvmiMIOSession session,PvmiKvp * parameters,int num_elements)1074 OSCL_EXPORT_REF PVMFStatus H223OutgoingChannel::releaseParameters(PvmiMIOSession session,
1075         PvmiKvp* parameters,
1076         int num_elements)
1077 {
1078     OSCL_UNUSED_ARG(session);
1079     OSCL_UNUSED_ARG(num_elements);
1080 
1081     if (parameters)
1082     {
1083         iKvpMemAlloc.deallocate((OsclAny*)parameters);
1084         return PVMFSuccess;
1085     }
1086     else
1087     {
1088         return PVMFFailure;
1089     }
1090 }
1091 
1092 ////////////////////////////////////////////////////////////////////////////
createContext(PvmiMIOSession session,PvmiCapabilityContext & context)1093 OSCL_EXPORT_REF void H223OutgoingChannel::createContext(PvmiMIOSession session, PvmiCapabilityContext& context)
1094 {
1095     OSCL_UNUSED_ARG(session);
1096     OSCL_UNUSED_ARG(context);
1097 }
1098 
1099 ////////////////////////////////////////////////////////////////////////////
setContextParameters(PvmiMIOSession session,PvmiCapabilityContext & context,PvmiKvp * parameters,int num_parameter_elements)1100 OSCL_EXPORT_REF void H223OutgoingChannel::setContextParameters(PvmiMIOSession session,
1101         PvmiCapabilityContext& context,
1102         PvmiKvp* parameters, int num_parameter_elements)
1103 {
1104     OSCL_UNUSED_ARG(session);
1105     OSCL_UNUSED_ARG(context);
1106     OSCL_UNUSED_ARG(parameters);
1107     OSCL_UNUSED_ARG(num_parameter_elements);
1108 }
1109 
1110 ////////////////////////////////////////////////////////////////////////////
DeleteContext(PvmiMIOSession session,PvmiCapabilityContext & context)1111 OSCL_EXPORT_REF void H223OutgoingChannel::DeleteContext(PvmiMIOSession session, PvmiCapabilityContext& context)
1112 {
1113     OSCL_UNUSED_ARG(session);
1114     OSCL_UNUSED_ARG(context);
1115 }
1116 
1117 ////////////////////////////////////////////////////////////////////////////
setParametersSync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements,PvmiKvp * & ret_kvp)1118 OSCL_EXPORT_REF void H223OutgoingChannel::setParametersSync(PvmiMIOSession session, PvmiKvp* parameters,
1119         int num_elements, PvmiKvp*& ret_kvp)
1120 {
1121     OSCL_UNUSED_ARG(session);
1122     PVMFStatus status = PVMFSuccess;
1123     ret_kvp = NULL;
1124 
1125     for (int32 i = 0; i < num_elements; i++)
1126     {
1127         status = VerifyAndSetParameter(&(parameters[i]), true);
1128         if (status != PVMFSuccess)
1129         {
1130             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::setParametersSync: Error - VerifiyAndSetParameter failed on parameter #%d", i));
1131             ret_kvp = &(parameters[i]);
1132             /* Silently ignore unrecognized codecs untill CapEx is supported by peer */
1133             //OSCL_LEAVE(OsclErrArgument);
1134         }
1135     }
1136 }
1137 
VerifyAndSetParameter(PvmiKvp * aKvp,bool aSetParam)1138 PVMFStatus H223OutgoingChannel::VerifyAndSetParameter(PvmiKvp* aKvp, bool aSetParam)
1139 {
1140     OSCL_UNUSED_ARG(aSetParam);
1141     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::VerifyAndSetParameter: aKvp=0x%x, aSetParam=%d", aKvp, aSetParam));
1142 
1143     if (!aKvp)
1144     {
1145         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::VerifyAndSetParameter: Error - Invalid key-value pair"));
1146         return PVMFFailure;
1147     }
1148 
1149     if (iDataType == NULL)
1150     {
1151         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::VerifyAndSetParameter: Error - DataType == NULL"));
1152         return PVMFErrNotSupported;
1153     }
1154 
1155     if (pv_mime_strcmp(aKvp->key, INPUT_FORMATS_VALTYPE) == 0)
1156     {
1157         PVCodecType_t codec_type = GetCodecType(iDataType);
1158         PVMFFormatType lcn_format_type = PVCodecTypeToPVMFFormatType(codec_type);
1159         if (pv_mime_strcmp(lcn_format_type.getMIMEStrPtr(), aKvp->value.pChar_value) != 0)
1160         {
1161             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::VerifyAndSetParameter: Error - Input format %s not supported", aKvp->value.pChar_value));
1162             return PVMFErrNotSupported;
1163         }
1164     }
1165     else if (pv_mime_strcmp(aKvp->key, PVMF_FORMAT_SPECIFIC_INFO_KEY) == 0)
1166     {
1167         ReceivedFSIFromPeer(aKvp);
1168     }
1169 
1170     return PVMFSuccess;
1171 }
1172 
1173 ////////////////////////////////////////////////////////////////////////////
setParametersAsync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements,PvmiKvp * & ret_kvp,OsclAny * context)1174 OSCL_EXPORT_REF PVMFCommandId H223OutgoingChannel::setParametersAsync(PvmiMIOSession session,
1175         PvmiKvp* parameters,
1176         int num_elements,
1177         PvmiKvp*& ret_kvp,
1178         OsclAny* context)
1179 {
1180     OSCL_UNUSED_ARG(session);
1181     OSCL_UNUSED_ARG(parameters);
1182     OSCL_UNUSED_ARG(num_elements);
1183     OSCL_UNUSED_ARG(ret_kvp);
1184     OSCL_UNUSED_ARG(context);
1185     return -1;
1186 }
1187 
1188 ////////////////////////////////////////////////////////////////////////////
getCapabilityMetric(PvmiMIOSession session)1189 OSCL_EXPORT_REF uint32 H223OutgoingChannel::getCapabilityMetric(PvmiMIOSession session)
1190 {
1191     OSCL_UNUSED_ARG(session);
1192     return 1;
1193 }
1194 
1195 ////////////////////////////////////////////////////////////////////////////
verifyParametersSync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements)1196 OSCL_EXPORT_REF PVMFStatus H223OutgoingChannel::verifyParametersSync(PvmiMIOSession session,
1197         PvmiKvp* parameters, int num_elements)
1198 {
1199     OSCL_UNUSED_ARG(session);
1200 
1201     PVMFStatus status = PVMFSuccess;
1202     for (int32 i = 0; (i < num_elements) && (status == PVMFSuccess); i++)
1203         status = VerifyAndSetParameter(&(parameters[i]), true);
1204 
1205     return status;
1206 }
1207 
HandlePortActivity(const PVMFPortActivity & aActivity)1208 void H223OutgoingChannel::HandlePortActivity(const PVMFPortActivity &aActivity)
1209 {
1210     if (aActivity.iType != PVMF_PORT_ACTIVITY_INCOMING_MSG &&
1211             aActivity.iType != PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY)
1212     {
1213         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::HandlePortActivity Unhandled port activity: %d", aActivity.iType));
1214         return;
1215     }
1216     PVMFStatus aStatus;
1217     PVMFSharedMediaMsgPtr aMsg;
1218     while (IncomingMsgQueueSize())
1219     {
1220         aStatus = DequeueIncomingMsg(aMsg);
1221         if (aStatus == PVMFSuccess)
1222         {
1223             PutData(aMsg);
1224         }
1225         else
1226         {
1227             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223OutgoingChannel::HandlePortActivity Failed to DeQueue incoming message: %d", aStatus));
1228             break;
1229         }
1230     }
1231 }
1232 
PeerConnect(PVMFPortInterface * aPort)1233 OSCL_EXPORT_REF PVMFStatus H223OutgoingControlChannel::PeerConnect(PVMFPortInterface* aPort)
1234 {
1235     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingControlChannel::PeerConnect aPort=0x%x", this, aPort));
1236     if (!aPort)
1237     {
1238         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "0x%x H223OutgoingControlChannel::PeerConnect: Error - Connecting to invalid port", this));
1239         return PVMFErrArgument;
1240     }
1241     if (iConnectedPort)
1242     {
1243         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_ERR, (0, "0x%x H223OutgoingControlChannel::PeerConnect: Error - Already connected", this));
1244         return PVMFFailure;
1245     }
1246 
1247     iConnectedPort = aPort;
1248     PortActivity(PVMF_PORT_ACTIVITY_CONNECT);
1249 
1250     return PVMFSuccess;
1251 
1252 }
PutData(PVMFSharedMediaMsgPtr aMsg)1253 PVMFStatus H223OutgoingControlChannel::PutData(PVMFSharedMediaMsgPtr aMsg)
1254 {
1255     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingControlChannel::PutData - iNumPendingPdus=%d,iNumMediaData=%d", iNumPendingPdus, iNumMediaData));
1256 
1257     PVMFSharedMediaDataPtr mediaData;
1258     convertToPVMFMediaData(mediaData, aMsg);
1259 
1260     PV_STAT_SET_TIME(iStartTime, iNumPacketsIn)
1261     PV_STAT_INCR(iNumPacketsIn, 1)
1262     PV_STAT_INCR(iNumSdusIn, 1)
1263     PV_STAT_INCR(iNumBytesIn, (mediaData->getFilledSize()))
1264 
1265     OsclSharedPtr<PVMFMediaDataImpl> pdu;
1266     pdu = iMediaFragGroupAlloc->allocate();
1267 
1268     if (!pdu)
1269     {
1270         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingControlChannel::PutData - Memory allocation failure on iMediaFragGroupAlloc->allocate\n"));
1271         return PVMFErrNoMemory;
1272     }
1273 
1274     TimeValue timenow;
1275     OsclRefCounterMemFrag frag;
1276     for (uint frag_num = 0; frag_num < mediaData->getNumFragments(); frag_num++)
1277     {
1278         mediaData->getMediaFragment(frag_num, frag);
1279         // Add data fragments
1280         pdu->appendMediaFragment(frag);
1281     }
1282 
1283     PVMFStatus status = iAl->CompletePacket(pdu);
1284     if (status != PVMFSuccess)
1285     {
1286         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingControlChannel::PutData - Memory allocation failure on iAl->CompletePacket()"));
1287         return status;
1288     }
1289 
1290     OsclRefCounterMemFrag fsi;
1291     bool fsi_available = mediaData->getFormatSpecificInfo(fsi);
1292     // Add it to the outgoing queue
1293     if (PVMFSuccess != AppendOutgoingPkt(pdu, timenow.to_msec(), (fsi_available ? &fsi : NULL)))
1294     {
1295         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingControlChannel::PutData - Memory allocation failure on AppendOutgoingPkt()"));
1296         return PVMFErrNoMemory;
1297     }
1298     return PVMFSuccess;
1299 }
1300 
SetDatapathLatency(uint32 aLatency)1301 void H223LogicalChannel::SetDatapathLatency(uint32 aLatency)
1302 {
1303     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223LogicalChannel::SetDatapathLatency lcn=%d, aLatency=%d", lcn, aLatency));
1304     iDatapathLatency = aLatency;
1305 }
1306 
setConfigParametersSync(PvmiKvp * selectedKvp,PvmiCapabilityAndConfig * aConfig,PVMFFormatType lcn_format_type,bool aTryTwice)1307 PVMFStatus H223LogicalChannel::setConfigParametersSync(PvmiKvp* selectedKvp,
1308         PvmiCapabilityAndConfig* aConfig,
1309         PVMFFormatType lcn_format_type,
1310         bool aTryTwice)
1311 {
1312     int32 err = 0;
1313     PvmiKvp* retKvp = NULL;
1314     if (!aTryTwice)
1315     {
1316         OSCL_TRY(err, aConfig->setParametersSync(NULL, selectedKvp, 1, retKvp););
1317         OSCL_FIRST_CATCH_ANY(err,
1318                              PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::setConfigParametersSync, Error:  setParametersSync failed, err=%d", err));
1319                              return PVMFFailure;
1320                             );
1321     }
1322     else
1323     {
1324         int32 err = 0;
1325         OSCL_TRY(err, aConfig->setParametersSync(NULL, selectedKvp, 1, retKvp););
1326         if (err)
1327         {
1328             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::setConfigParametersSync, Error:  setParametersSync failed for pChar value, trying uint32, err=%d", err));
1329             selectedKvp->value.pChar_value = OSCL_STATIC_CAST(mbchar*, lcn_format_type.getMIMEStrPtr());
1330             err = 0;
1331             OSCL_TRY(err, aConfig->setParametersSync(NULL, selectedKvp, 1, retKvp););
1332             if (err)
1333             {
1334                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::setConfigParametersSync, Error:  setParametersSync failed, err=%d", err));
1335                 return PVMFFailure;
1336             }
1337         }
1338     }
1339     return PVMFSuccess;
1340 }
H223IncomingChannel(TPVChannelId num,bool segmentable,OsclSharedPtr<AdaptationLayer> & al,PS_DataType data_type,LogicalChannelObserver * observer,uint32 bitrate,uint32 sample_interval,uint32 num_media_data)1341 H223IncomingChannel::H223IncomingChannel(TPVChannelId num,
1342         bool segmentable,
1343         OsclSharedPtr<AdaptationLayer>& al,
1344         PS_DataType data_type,
1345         LogicalChannelObserver* observer,
1346         uint32 bitrate,
1347         uint32 sample_interval,
1348         uint32 num_media_data)
1349         : H223LogicalChannel(num, segmentable, al, data_type, observer, bitrate, sample_interval, num_media_data),
1350         iMediaMsgMemoryPool(NULL),
1351         iMediaFragGroupAlloc(NULL),
1352         iPduPktMemPool(NULL),
1353         iMediaDataAlloc(&iMemAlloc),
1354         iPduSize(al->GetPduSize()),
1355         iCurPduSize(0),
1356         iRenderingSkew(0)
1357 {
1358     iLogger = PVLogger::GetLoggerObject("3g324m.h223.H223IncomingChannel");
1359     iIncomingAudioLogger = PVLogger::GetLoggerObject("datapath.incoming.audio.h223.lcn");
1360     iIncomingVideoLogger = PVLogger::GetLoggerObject("datapath.incoming.video.h223.lcn");
1361     iAlPduFragPos = NULL;
1362     ResetStats();
1363 }
1364 
~H223IncomingChannel()1365 H223IncomingChannel::~H223IncomingChannel()
1366 {
1367     Flush();
1368     OsclRefCounterMemFrag frag;
1369     iAlPduFrag = frag;
1370     if (iMediaFragGroupAlloc)
1371     {
1372         iMediaFragGroupAlloc->removeRef();
1373     }
1374     if (iPduPktMemPool)
1375     {
1376         OSCL_DELETE(iPduPktMemPool);
1377     }
1378     if (iMediaMsgMemoryPool)
1379     {
1380         OSCL_DELETE(iMediaMsgMemoryPool);
1381     }
1382 }
1383 
Init()1384 void H223IncomingChannel::Init()
1385 {
1386     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Init"));
1387     H223LogicalChannel::Init();
1388 
1389     int bitrate = (GetBitrate() > 0) ? GetBitrate() : DEF_CHANNEL_BITRATE;
1390     int mem_size = (DEF_INCOMING_CHANNEL_BUFFER_SIZE_MS * bitrate) >> PV2WAY_BPS_TO_BYTES_PER_MSEC_RIGHT_SHIFT;
1391     int num_fragments = (mem_size / H223_INCOMING_CHANNEL_FRAGMENT_SIZE) + 1;
1392     iMediaMsgMemoryPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (H223_INCOMING_CHANNEL_NUM_MEDIA_MSG));
1393     if (iMediaMsgMemoryPool == NULL)
1394     {
1395         OSCL_LEAVE(PVMFErrNoMemory);
1396     }
1397     iMediaMsgMemoryPool->enablenullpointerreturn();
1398 
1399     iPduPktMemPool = OSCL_NEW(OsclMemPoolFixedChunkAllocator, (H223_INCOMING_CHANNEL_NUM_MEDIA_DATA));
1400     if (iPduPktMemPool == NULL)
1401     {
1402         OSCL_LEAVE(PVMFErrNoMemory);
1403     }
1404     iPduPktMemPool->enablenullpointerreturn();
1405 
1406     iMediaFragGroupAlloc = OSCL_NEW(PVMFMediaFragGroupCombinedAlloc<OsclMemAllocator>, (H223_INCOMING_CHANNEL_NUM_MEDIA_DATA, H223_INCOMING_CHANNEL_NUM_FRAGS_IN_MEDIA_DATA, iPduPktMemPool));
1407     if (iMediaFragGroupAlloc == NULL)
1408     {
1409         OSCL_LEAVE(PVMFErrNoMemory);
1410     }
1411     iMediaFragGroupAlloc->create();
1412 
1413     iMemFragmentAlloc.SetLeaveOnAllocFailure(false);
1414     iMemFragmentAlloc.size((uint16)num_fragments, (uint16)H223_INCOMING_CHANNEL_FRAGMENT_SIZE);
1415 
1416     ResetAlPdu();
1417     AllocateAlPdu();
1418     iCurTimestamp = 0;
1419     iNumSdusIn = 0;
1420     iNumPdusIn = 0;
1421 }
1422 
ResetAlPdu()1423 OsclAny H223IncomingChannel::ResetAlPdu()
1424 {
1425     iAlPduFragPos = NULL;
1426     iCurPduSize = 0;
1427     OsclRefCounterMemFrag frag;
1428     iAlPduFrag = frag;
1429     iAlPduMediaData.Unbind();
1430 }
1431 
AllocateAlPdu()1432 OsclAny H223IncomingChannel::AllocateAlPdu()
1433 {
1434     iAlPduMediaData = iMediaFragGroupAlloc->allocate();
1435     if (iAlPduMediaData.GetRep() == NULL)
1436     {
1437         return;
1438     }
1439     AppendAlPduFrag();
1440 }
1441 
AppendAlPduFrag()1442 OsclAny H223IncomingChannel::AppendAlPduFrag()
1443 {
1444     OsclRefCounterMemFrag ref_counter_mem_frag = iMemFragmentAlloc.get();
1445     if (ref_counter_mem_frag.getMemFragPtr() == NULL)
1446     {
1447         return;
1448     }
1449     ref_counter_mem_frag.getMemFrag().len = 0;
1450     iAlPduFrag = ref_counter_mem_frag;
1451     iAlPduFragPos = (uint8*)iAlPduFrag.getMemFragPtr();
1452 }
1453 
CopyAlPduData(uint8 * buf,uint16 len)1454 uint32 H223IncomingChannel::CopyAlPduData(uint8* buf, uint16 len)
1455 {
1456     int32 remaining = len;
1457     uint32 copied = 0;
1458     do
1459     {
1460         copied = CopyToCurrentFrag(buf, (uint16)remaining);
1461         buf += copied;
1462         remaining -= copied;
1463     }
1464     while (remaining && copied);
1465     return (uint32)(len - remaining);
1466 }
1467 
CopyToCurrentFrag(uint8 * buf,uint16 len)1468 uint32 H223IncomingChannel::CopyToCurrentFrag(uint8* buf, uint16 len)
1469 {
1470     if (iAlPduMediaData.GetRep() == NULL)
1471     {
1472         AllocateAlPdu();
1473     }
1474     else if (iAlPduFragPos == NULL)
1475     {
1476         AppendAlPduFrag();
1477     }
1478     if (iAlPduFragPos == NULL)
1479     {
1480         return 0;
1481     }
1482 
1483     uint32 space_in_current_frag = ((uint8*)iAlPduFrag.getMemFragPtr() + iAlPduFrag.getCapacity() - iAlPduFragPos);
1484     OSCL_ASSERT(space_in_current_frag > 0);
1485     uint32 num_bytes_copied = (len > space_in_current_frag) ? space_in_current_frag : len;
1486     oscl_memcpy(iAlPduFragPos, buf, num_bytes_copied);
1487     iAlPduFrag.getMemFrag().len += num_bytes_copied;
1488     iAlPduFragPos += num_bytes_copied;
1489     space_in_current_frag -= num_bytes_copied;
1490     if (space_in_current_frag == 0)
1491     {
1492         iAlPduMediaData->appendMediaFragment(iAlPduFrag);
1493         iAlPduFragPos = NULL;
1494     }
1495     PVLOGGER_LOG_USE_ONLY(
1496         if (iAlPduMediaData->getFilledSize() > iPduSize)
1497 {
1498     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::CopyToCurrentFrag WARNING current pdu size=%d > iPduSize=%d", iAlPduMediaData->getFilledSize(), iPduSize));
1499     }
1500     );
1501     return num_bytes_copied;
1502 }
1503 
PreAlPduData()1504 void H223IncomingChannel::PreAlPduData()
1505 
1506 {
1507     if (iSendFormatSpecificInfo)
1508     {
1509         SendFormatSpecificInfo();
1510     }
1511 
1512     if (iPaused)
1513     {
1514         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::PreAlPduData Logical channel paused.  Dropping media data."));
1515         return;
1516     }
1517 }
1518 
AlPduData(uint8 * buf,uint16 len)1519 PVMFStatus H223IncomingChannel::AlPduData(uint8* buf, uint16 len)
1520 {
1521     PV_STAT_INCR(iNumBytesIn, len)
1522     PV_STAT_SET_TIME(iStartTime, iNumBytesIn)
1523 
1524     PreAlPduData();
1525     if (PVMFSuccess != DispatchPendingSdus())
1526     {
1527         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::AlPduData lcn=%d, Failed to dispatch pending sdus", lcn));
1528     }
1529     if (iAlPduMediaData.GetRep() == NULL || iAlPduMediaData->getFilledSize() == 0)
1530     {
1531         bool overflow = false;
1532         iClock->GetCurrentTime32(iCurTimestamp, overflow, PVMF_MEDIA_CLOCK_MSEC);
1533     }
1534     uint32 copied = CopyAlPduData(buf, len);
1535     return (copied == len) ? PVMFSuccess : PVMFFailure;
1536 }
1537 
AlDispatch()1538 PVMFStatus H223IncomingChannel::AlDispatch()
1539 {
1540     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::AlDispatch lcn=%d, iCurPduSize=%d, sn=%d", lcn, iCurPduSize, iNumSdusIn));
1541     IncomingALPduInfo info;
1542 
1543     if (iPaused)
1544     {
1545         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::AlDispatch Logical channel paused."));
1546         return PVMFFailure;
1547     }
1548 
1549     /*  Nothing to dispatch */
1550     if (!iAlPduMediaData.GetRep())
1551     {
1552         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::AlDispatch Nothing to dispatch."));
1553         ResetAlPdu();
1554         return PVMFSuccess;
1555     }
1556 
1557     /*  Add pending fragment to the media message */
1558     if (iAlPduFragPos)
1559     {
1560         iAlPduMediaData->appendMediaFragment(iAlPduFrag);
1561     }
1562 
1563     /* Parse AL headers etc */
1564     iAl->ParsePacket(iAlPduMediaData, info);
1565     int32 len = info.sdu_size;
1566     if (len <= 0)
1567     {
1568         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223OutgoingChannel::AlDispatch Empty SDU lcn=%d, len=%d", lcn, len));
1569         ResetAlPdu();
1570         return PVMFErrCorrupt;
1571     }
1572 
1573     PV_STAT_INCR_COND(iNumCrcErrors, 1, info.crc_error)
1574     PV_STAT_INCR_COND(iNumSeqNumErrors, 1, info.seq_num_error)
1575     PVMFStatus status = PVMFSuccess;
1576 
1577     // set the errors flag
1578     uint32 errorsFlag = 0;
1579     if (info.crc_error)
1580     {
1581         errorsFlag |= PVMF_MEDIA_DATA_BIT_ERRORS;
1582         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::AlDispatch CRC error lcn=%d, size=%d", lcn, len));
1583         status =  PVMFErrCorrupt;
1584     }
1585     else
1586     {
1587         PV_STAT_INCR(iNumSdusIn, 1)
1588     }
1589     if (info.seq_num_error)
1590     {
1591         errorsFlag |= PVMF_MEDIA_DATA_PACKET_LOSS;
1592         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::AlDispatch Sequence number error lcn=%d, size=%d", lcn, len));
1593         status = PVMFErrCorrupt;
1594     }
1595 
1596     OsclSharedPtr<PVMFMediaData> aMediaData = PVMFMediaData::createMediaData(iAlPduMediaData, iMediaMsgMemoryPool);
1597     if (aMediaData.GetRep() == NULL)
1598     {
1599         return PVMFErrNoMemory;
1600     }
1601 
1602     PVMFTimestamp baseTimestamp = 0;
1603     SetSampleTimestamps(baseTimestamp);
1604     aMediaData->setTimestamp(baseTimestamp);
1605 
1606     iAlPduMediaData->setErrorsFlag(errorsFlag);
1607 
1608     PVMFSharedMediaMsgPtr aMediaMsg;
1609     convertToPVMFMediaMsg(aMediaMsg, aMediaData);
1610 
1611     PVMFFormatType mediaType = GetFormatType();
1612     if (mediaType.isCompressed() && mediaType.isAudio())
1613     {
1614         // we are using only full audio frames
1615         aMediaData->setMarkerInfo(PVMF_MEDIA_DATA_MARKER_INFO_M_BIT);
1616     }
1617 
1618     if (IsConnected())
1619     {
1620         if (mediaType.isCompressed() && mediaType.isAudio())
1621         {
1622             PVMF_INCOMING_AUDIO_LOGDATATRAFFIC((0, "Incoming audio SDU received. Stats: Entry time=%d, lcn=%d, size=%d,FmtType=%s", iCurTimestamp, lcn, aMediaData->getFilledSize(), mediaType.getMIMEStrPtr()));
1623         }
1624         else if (mediaType.isCompressed() && mediaType.isVideo())
1625         {
1626             PVMF_INCOMING_VIDEO_LOGDATATRAFFIC((0, "Incoming video SDU received.Stats: Entry time=%d, lcn=%d, size=%d,FmtType=%s", iCurTimestamp, lcn, aMediaData->getFilledSize(), mediaType.getMIMEStrPtr()));
1627         }
1628         PVMFStatus dispatch_status = QueueOutgoingMsg(aMediaMsg);
1629         if (dispatch_status != PVMFSuccess)
1630         {
1631             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::AlDispatch Failed to queue outgoing media message lcn=%d, size=%d, status=%d", lcn, len, dispatch_status));
1632             status = dispatch_status;
1633         }
1634     }
1635     else if (IsSegmentable())
1636     {
1637         iPendingSdus.push_back(aMediaMsg);
1638     }
1639     else
1640     {
1641         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::AlDispatchL Dropping pdu lcn=%d, iCurPduSize=%d", lcn, iCurPduSize));
1642         status = PVMFErrNotReady;
1643     }
1644     ResetAlPdu();
1645     AllocateAlPdu();
1646     return status;
1647 }
1648 
Flush()1649 OsclAny H223IncomingChannel::Flush()
1650 {
1651     PV_STAT_INCR(iNumBytesFlushed, (iAlPduFragPos - (uint8*)iAlPduFrag.getMemFragPtr()))
1652     PV_STAT_INCR_COND(iNumAbort, 1, (iAlPduFragPos - (uint8*)iAlPduFrag.getMemFragPtr()))
1653     iPendingSdus.clear();
1654     ResetAlPdu();
1655 
1656 }
1657 
Connect(PVMFPortInterface * aPort)1658 PVMFStatus H223IncomingChannel::Connect(PVMFPortInterface* aPort)
1659 {
1660     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect lcn(%d)\n", lcn));
1661     if (iConnectedPort)
1662     {
1663         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect Error: Already connected"));
1664         return PVMFFailure;
1665     }
1666 
1667     PvmiCapabilityAndConfig* config = NULL;
1668     OsclAny * tempInterface = NULL;
1669     aPort->QueryInterface(PVMI_CAPABILITY_AND_CONFIG_PVUUID, tempInterface);
1670     config = OSCL_STATIC_CAST(PvmiCapabilityAndConfig*, tempInterface);
1671     if (!config)
1672     {
1673         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect: Error - Peer port does not support capability interface"));
1674         return PVMFFailure;
1675     }
1676 
1677     PVMFStatus status = NegotiateOutputSettings(config);
1678 
1679     if (status != PVMFSuccess)
1680     {
1681         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect: Error - Settings negotiation failed. status=%d", status));
1682         return status;
1683     }
1684 
1685     //Automatically connect the peer.
1686     if ((status = aPort->PeerConnect(this)) != PVMFSuccess)
1687     {
1688         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect: Error - Peer Connect failed. status=%d", status));
1689         return status;
1690     }
1691 
1692     iConnectedPort = aPort;
1693 
1694     //Check the BOS command status
1695     status = SendBeginOfStreamMediaCommand();
1696 
1697     if (status != PVMFSuccess)
1698     {
1699         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect: Failed to send BOS message status=%d", status));
1700         return status;
1701     }
1702 
1703     /* Send any format specific info if available */
1704     if (iSendFormatSpecificInfo)
1705         SendFormatSpecificInfo();
1706 
1707     DispatchPendingSdus();
1708 
1709     PortActivity(PVMF_PORT_ACTIVITY_CONNECT);
1710 
1711     return PVMFSuccess;
1712 }
1713 
ResetStats()1714 OsclAny H223IncomingChannel::ResetStats()
1715 {
1716     iNumSdusIn = 0;
1717     iNumBytesIn = 0;
1718     iSduSizeExceededCnt = 0;
1719     iNumCrcErrors = 0;
1720     iNumSeqNumErrors = 0;
1721     iNumBytesFlushed = 0;
1722     iNumAbort = 0;
1723 }
1724 
LogStats()1725 OsclAny H223IncomingChannel::LogStats()
1726 {
1727     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Incoming Logical Channel %d Statistics:\n", lcn));
1728     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus received - %d\n", iNumSdusIn));
1729     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes received - %d\n", iNumBytesIn));
1730     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num times sdu size exceeded - %d\n", iSduSizeExceededCnt));
1731     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus with CRC errors - %d\n", iNumCrcErrors));
1732     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus with sequence number errors - %d\n", iNumSeqNumErrors));
1733     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num sdus aborted - %d\n", iNumAbort));
1734     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "Num bytes aborted - %d\n", iNumBytesFlushed));
1735 }
1736 
DispatchPendingSdus()1737 PVMFStatus H223IncomingChannel::DispatchPendingSdus()
1738 {
1739     if (!iConnectedPort)
1740         return PVMFFailure;
1741     if (iPendingSdus.size())
1742     {
1743         /* Dispatch any pending sdus */
1744         for (unsigned i = 0; i < iPendingSdus.size(); i++)
1745         {
1746             PVMFStatus status = QueueOutgoingMsg(iPendingSdus[i]);
1747             if (status != PVMFSuccess)
1748             {
1749                 PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect Error: PutData failed for buffered sdus lcn=%d, status=%d, i=%d", lcn, status, i));
1750                 iObserver->LogicalChannelError(INCOMING, lcn, status);
1751                 return PVMFFailure;
1752             }
1753         }
1754         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::Connect lcn=%d,num sdus=%d", lcn, iPendingSdus.size()));
1755         iPendingSdus.clear();
1756     }
1757     return PVMFSuccess;
1758 }
1759 
SendFormatSpecificInfo()1760 OsclAny H223IncomingChannel::SendFormatSpecificInfo()
1761 {
1762     //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"H223IncomingChannel::SendFormatSpecificInfo lcn=%d, iFormatSpecificInfoLen=%d, iFormatSpecificInfo=%x", lcn,iFormatSpecificInfoLen,iFormatSpecificInfo));
1763     //printBuffer(iLogger, iFormatSpecificInfo, (uint16)iFormatSpecificInfoLen);
1764     if (!IsConnected())
1765     {
1766         //PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0,"H223IncomingChannel::SendFormatSpecificInfo ERROR Not connected."));
1767         //OSCL_LEAVE(PVMFErrNotReady);
1768         return;
1769     }
1770 
1771     // Create mem frag for VOL header
1772     // Create new media data buffer for header fragment
1773     OsclSharedPtr<PVMFMediaDataImpl> hdrImpl = iMediaDataAlloc.allocate(iFormatSpecificInfoLen);
1774     if (!hdrImpl)
1775     {
1776         return;
1777     }
1778     PVMFSharedMediaDataPtr hdrMediaData = PVMFMediaData::createMediaData(hdrImpl);
1779     OsclRefCounterMemFrag myVolHeader;
1780     hdrMediaData->getMediaFragment(0, myVolHeader);
1781     oscl_memcpy(myVolHeader.getMemFragPtr(), iFormatSpecificInfo, iFormatSpecificInfoLen);
1782     myVolHeader.getMemFrag().len = iFormatSpecificInfoLen;
1783 
1784     // Create new media data buffer for the message
1785     OsclSharedPtr<PVMFMediaDataImpl> emptyImpl = iMediaDataAlloc.allocate(0);
1786     if (!emptyImpl)
1787     {
1788         return;
1789     }
1790     PVMFSharedMediaDataPtr volData = PVMFMediaData::createMediaData(emptyImpl);
1791 
1792     // Set format specific info in media data message
1793     volData->setFormatSpecificInfo(myVolHeader);
1794 
1795     // Send VOL header to downstream node
1796     PVMFSharedMediaMsgPtr volMsg;
1797     convertToPVMFMediaMsg(volMsg, volData);
1798     PVMFStatus status = QueueOutgoingMsg(volMsg);
1799     if (status != PVMFSuccess)
1800     {
1801         OSCL_LEAVE(status);
1802     }
1803     iSendFormatSpecificInfo = false;
1804 }
1805 
MuxSduData()1806 MuxSduData::MuxSduData()
1807 {
1808     size = 0;
1809     cur_frag_num = 0;
1810     cur_pos = 0;
1811 }
NegotiateOutputSettings(PvmiCapabilityAndConfig * aConfig)1812 PVMFStatus H223IncomingChannel::NegotiateOutputSettings(PvmiCapabilityAndConfig* aConfig)
1813 {
1814     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::NegotiateInputSettings, aConfig=%x", aConfig));
1815 
1816     PvmiKvp* kvp = NULL;
1817     int numParams = 0;
1818     int32 i = 0;
1819 
1820     // Get supported input formats from peer
1821     PVMFStatus status = aConfig->getParametersSync(NULL,
1822                         OSCL_CONST_CAST(char*, INPUT_FORMATS_CAP_QUERY),
1823                         kvp, numParams, NULL);
1824 
1825     if (status != PVMFSuccess)
1826     {
1827         status = aConfig->getParametersSync(NULL,
1828                                             OSCL_CONST_CAST(char*, "x-pvmf/video/decode/input_formats"),
1829                                             kvp, numParams, NULL);
1830     }
1831 
1832     if (status != PVMFSuccess || numParams == 0)
1833     {
1834         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::NegotiateInputSettings, Error:  getParametersSync failed.  status=%d", status));
1835 
1836         return PVMFSuccess;
1837     }
1838 
1839     PvmiKvp* selectedKvp = NULL;
1840     PVCodecType_t codec_type = GetCodecType(iDataType);
1841     PVMFFormatType lcn_format_type = PVCodecTypeToPVMFFormatType(codec_type);
1842 
1843     for (i = 0; i < numParams && !selectedKvp; i++)
1844     {
1845         if (lcn_format_type == kvp[i].value.pChar_value)
1846             selectedKvp = &(kvp[i]);
1847     }
1848 
1849     if (!selectedKvp)
1850     {
1851         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::NegotiateInputSettings, Error:  Input format not supported by peer"));
1852         return PVMFFailure;
1853     }
1854 
1855     /* This is for the silly problem of MIO components having the convention
1856        of returning uint32 for a query and requiring pChar for a setting
1857        we don't know if we are talking to an MIO or a decoder node
1858        (which will want a uint32), so we try both.  Try the pchar
1859        first, because if its expecting pchar and gets uint32, it will
1860        crash.
1861     */
1862     if (PVMFSuccess != setConfigParametersSync(selectedKvp, aConfig, lcn_format_type, true))
1863         return PVMFFailure;
1864 
1865     aConfig->releaseParameters(NULL, kvp, numParams);
1866     kvp = NULL;
1867     numParams = 0;
1868 
1869     return PVMFSuccess;
1870 }
1871 
1872 ////////////////////////////////////////////////////////////////////////////
1873 //                  PvmiCapabilityAndConfig
1874 ////////////////////////////////////////////////////////////////////////////
setObserver(PvmiConfigAndCapabilityCmdObserver * aObserver)1875 OSCL_EXPORT_REF void H223IncomingChannel::setObserver(PvmiConfigAndCapabilityCmdObserver* aObserver)
1876 {
1877     // Not supported
1878     OSCL_UNUSED_ARG(aObserver);
1879     OSCL_LEAVE(OsclErrNotSupported);
1880 }
1881 
1882 ////////////////////////////////////////////////////////////////////////////
getParametersSync(PvmiMIOSession session,PvmiKeyType identifier,PvmiKvp * & parameters,int & num_parameter_elements,PvmiCapabilityContext context)1883 OSCL_EXPORT_REF PVMFStatus H223IncomingChannel::getParametersSync(PvmiMIOSession session,
1884         PvmiKeyType identifier,
1885         PvmiKvp*& parameters,
1886         int& num_parameter_elements,
1887         PvmiCapabilityContext context)
1888 {
1889     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::getParametersSync"));
1890     OSCL_UNUSED_ARG(session);
1891     OSCL_UNUSED_ARG(context);
1892 
1893     parameters = NULL;
1894     num_parameter_elements = 0;
1895 
1896     if (pv_mime_strcmp(identifier, OUTPUT_FORMATS_CAP_QUERY) == 0)
1897     {
1898         num_parameter_elements = 1;
1899         PVMFStatus status = AllocateKvp(iKvpMemAlloc, parameters,
1900                                         OSCL_CONST_CAST(char*, OUTPUT_FORMATS_VALTYPE),
1901                                         num_parameter_elements);
1902         if (status != PVMFSuccess)
1903         {
1904             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::getParametersSync: Error - AllocateKvp failed. status=%d", status));
1905             return status;
1906         }
1907         PVCodecType_t codec_type = GetCodecType(iDataType);
1908         PVMFFormatType format = PVCodecTypeToPVMFFormatType(codec_type).getMIMEStrPtr();
1909         if (format == PVMF_MIME_AMR_IF2)
1910             parameters[0].value.pChar_value = (char*) PVMF_MIME_AMR_IF2;
1911         else if (format == PVMF_MIME_PCM16)
1912             parameters[0].value.pChar_value = (char*) PVMF_MIME_PCM16;
1913         else if (format ==  PVMF_MIME_YUV420)
1914             parameters[0].value.pChar_value = (char*) PVMF_MIME_YUV420;
1915         else if (format ==  PVMF_MIME_M4V)
1916             parameters[0].value.pChar_value = (char*) PVMF_MIME_M4V;
1917         else if (format ==  PVMF_MIME_H2632000)
1918             parameters[0].value.pChar_value = (char*) PVMF_MIME_H2632000;
1919         else if (format ==  PVMF_MIME_H2631998)
1920             parameters[0].value.pChar_value = (char*) PVMF_MIME_H2631998;
1921         else
1922             parameters[0].value.pChar_value = (char*) PVMF_MIME_FORMAT_UNKNOWN;
1923 
1924     }
1925 
1926     return PVMFSuccess;
1927 }
1928 
1929 ////////////////////////////////////////////////////////////////////////////
releaseParameters(PvmiMIOSession session,PvmiKvp * parameters,int num_elements)1930 OSCL_EXPORT_REF PVMFStatus H223IncomingChannel::releaseParameters(PvmiMIOSession session,
1931         PvmiKvp* parameters,
1932         int num_elements)
1933 {
1934     OSCL_UNUSED_ARG(session);
1935     OSCL_UNUSED_ARG(num_elements);
1936 
1937     if (parameters)
1938     {
1939         iKvpMemAlloc.deallocate((OsclAny*)parameters);
1940         return PVMFSuccess;
1941     }
1942     else
1943     {
1944         return PVMFFailure;
1945     }
1946 }
1947 
1948 ////////////////////////////////////////////////////////////////////////////
createContext(PvmiMIOSession session,PvmiCapabilityContext & context)1949 OSCL_EXPORT_REF void H223IncomingChannel::createContext(PvmiMIOSession session, PvmiCapabilityContext& context)
1950 {
1951     OSCL_UNUSED_ARG(session);
1952     OSCL_UNUSED_ARG(context);
1953 }
1954 
1955 ////////////////////////////////////////////////////////////////////////////
setContextParameters(PvmiMIOSession session,PvmiCapabilityContext & context,PvmiKvp * parameters,int num_parameter_elements)1956 OSCL_EXPORT_REF void H223IncomingChannel::setContextParameters(PvmiMIOSession session,
1957         PvmiCapabilityContext& context,
1958         PvmiKvp* parameters, int num_parameter_elements)
1959 {
1960     OSCL_UNUSED_ARG(session);
1961     OSCL_UNUSED_ARG(context);
1962     OSCL_UNUSED_ARG(parameters);
1963     OSCL_UNUSED_ARG(num_parameter_elements);
1964 }
1965 
1966 ////////////////////////////////////////////////////////////////////////////
DeleteContext(PvmiMIOSession session,PvmiCapabilityContext & context)1967 OSCL_EXPORT_REF void H223IncomingChannel::DeleteContext(PvmiMIOSession session, PvmiCapabilityContext& context)
1968 {
1969     OSCL_UNUSED_ARG(session);
1970     OSCL_UNUSED_ARG(context);
1971 }
1972 
1973 ////////////////////////////////////////////////////////////////////////////
setParametersSync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements,PvmiKvp * & ret_kvp)1974 OSCL_EXPORT_REF void H223IncomingChannel::setParametersSync(PvmiMIOSession session, PvmiKvp* parameters,
1975         int num_elements, PvmiKvp*& ret_kvp)
1976 {
1977     OSCL_UNUSED_ARG(session);
1978     PVMFStatus status = PVMFSuccess;
1979     ret_kvp = NULL;
1980 
1981     for (int32 i = 0; i < num_elements; i++)
1982     {
1983         status = VerifyAndSetParameter(&(parameters[i]), true);
1984         if (status != PVMFSuccess)
1985         {
1986             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::setParametersSync: Error - VerifiyAndSetParameter failed on parameter #%d", i));
1987             ret_kvp = &(parameters[i]);
1988             /* Silently ignore unrecognized codecs untill CapEx is supported by peer */
1989             //OSCL_LEAVE(OsclErrArgument);
1990         }
1991     }
1992 }
1993 
VerifyAndSetParameter(PvmiKvp * aKvp,bool aSetParam)1994 PVMFStatus H223IncomingChannel::VerifyAndSetParameter(PvmiKvp* aKvp, bool aSetParam)
1995 {
1996     OSCL_UNUSED_ARG(aSetParam);
1997     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::VerifyAndSetParameter: aKvp=0x%x, aSetParam=%d", aKvp, aSetParam));
1998 
1999     if (!aKvp)
2000     {
2001         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::VerifyAndSetParameter: Error - Invalid key-value pair"));
2002         return PVMFFailure;
2003     }
2004 
2005     if (iDataType == NULL)
2006     {
2007         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::VerifyAndSetParameter: Error - DataType == NULL"));
2008         return PVMFErrNotSupported;
2009     }
2010 
2011     if (pv_mime_strcmp(aKvp->key, OUTPUT_FORMATS_VALTYPE) == 0)
2012     {
2013         PVCodecType_t codec_type = GetCodecType(iDataType);
2014         PVMFFormatType lcn_format_type = PVCodecTypeToPVMFFormatType(codec_type);
2015         if (lcn_format_type != aKvp->value.pChar_value)
2016         {
2017             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::VerifyAndSetParameter: Error - Output format %s not supported", aKvp->value.pChar_value));
2018             return PVMFErrNotSupported;
2019         }
2020     }
2021 
2022     return PVMFSuccess;
2023 }
2024 
2025 ////////////////////////////////////////////////////////////////////////////
setParametersAsync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements,PvmiKvp * & ret_kvp,OsclAny * context)2026 OSCL_EXPORT_REF PVMFCommandId H223IncomingChannel::setParametersAsync(PvmiMIOSession session,
2027         PvmiKvp* parameters,
2028         int num_elements,
2029         PvmiKvp*& ret_kvp,
2030         OsclAny* context)
2031 {
2032     OSCL_UNUSED_ARG(session);
2033     OSCL_UNUSED_ARG(parameters);
2034     OSCL_UNUSED_ARG(num_elements);
2035     OSCL_UNUSED_ARG(ret_kvp);
2036     OSCL_UNUSED_ARG(context);
2037     return -1;
2038 }
2039 
2040 ////////////////////////////////////////////////////////////////////////////
getCapabilityMetric(PvmiMIOSession session)2041 OSCL_EXPORT_REF uint32 H223IncomingChannel::getCapabilityMetric(PvmiMIOSession session)
2042 {
2043     OSCL_UNUSED_ARG(session);
2044     return 1;
2045 }
2046 
2047 ////////////////////////////////////////////////////////////////////////////
verifyParametersSync(PvmiMIOSession session,PvmiKvp * parameters,int num_elements)2048 OSCL_EXPORT_REF PVMFStatus H223IncomingChannel::verifyParametersSync(PvmiMIOSession session,
2049         PvmiKvp* parameters, int num_elements)
2050 {
2051     OSCL_UNUSED_ARG(session);
2052 
2053     PVMFStatus status = PVMFSuccess;
2054     for (int32 i = 0; (i < num_elements) && (status == PVMFSuccess); i++)
2055         status = VerifyAndSetParameter(&(parameters[i]), true);
2056 
2057     return status;
2058 }
2059 
HandlePortActivity(const PVMFPortActivity & aActivity)2060 void H223IncomingChannel::HandlePortActivity(const PVMFPortActivity &aActivity)
2061 {
2062     if (aActivity.iType != PVMF_PORT_ACTIVITY_OUTGOING_MSG &&
2063             aActivity.iType != PVMF_PORT_ACTIVITY_CONNECTED_PORT_READY)
2064     {
2065         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::HandlePortActivity Unhandled port activity: %d", aActivity.iType));
2066         return;
2067     }
2068     PVMFStatus aStatus;
2069     PVMFSharedMediaMsgPtr aMsg;
2070     while (OutgoingMsgQueueSize())
2071     {
2072         aStatus = Send();
2073         if (aStatus != PVMFSuccess)
2074         {
2075             PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "H223IncomingChannel::HandlePortActivity Failed to DeQueue incoming message: %d", aStatus));
2076             break;
2077         }
2078     }
2079 }
2080 
SendBeginOfStreamMediaCommand()2081 PVMFStatus H223IncomingChannel::SendBeginOfStreamMediaCommand()
2082 {
2083     PVMFSharedMediaCmdPtr sharedMediaCmdPtr = PVMFMediaCmd::createMediaCmd();
2084     sharedMediaCmdPtr->setFormatID(PVMF_MEDIA_CMD_BOS_FORMAT_ID);
2085 
2086     sharedMediaCmdPtr->setTimestamp(iCurTimestamp);
2087 
2088     uint32 seqNum = 0;
2089     uint32 streamID = 0;
2090     sharedMediaCmdPtr->setSeqNum(seqNum);
2091 
2092     PVMFSharedMediaMsgPtr mediaMsgOut;
2093     convertToPVMFMediaCmdMsg(mediaMsgOut, sharedMediaCmdPtr);
2094     mediaMsgOut->setStreamID(streamID);
2095 
2096     PVMFStatus status = QueueOutgoingMsg(mediaMsgOut);
2097     if (status != PVMFSuccess)
2098     {
2099         // Output queue is busy, so wait for the output queue being ready
2100         PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING,
2101                         (0, "H223IncomingChannel::SendBeginOfMediaStreamCommand: Outgoing queue busy. "));
2102         return status;
2103     }
2104     PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "H223IncomingChannel::SendBeginOfMediaStreamCommand() BOS Sent StreamId %d ", streamID));
2105     return status;
2106 }
2107 
SetSampleTimestamps(PVMFTimestamp & aTSOffset)2108 void H223IncomingChannel::SetSampleTimestamps(PVMFTimestamp& aTSOffset)
2109 {
2110     iRenderingSkew = iAudioLatency - iVideoLatency;
2111     uint32 skewDelta = 0;
2112     if (iRenderingSkew >= (int32)iIncomingSkew)
2113     {
2114         skewDelta = iRenderingSkew - iIncomingSkew;
2115         if (iMediaType.isCompressed() && iMediaType.isAudio())
2116         {
2117             aTSOffset = (PVMFTimestamp)(iAudioLatency + PARSING_JITTER_DURATION);
2118         }
2119         else if (iMediaType.isCompressed() && iMediaType.isVideo())
2120         {
2121             aTSOffset = (PVMFTimestamp)(iVideoLatency + skewDelta + PARSING_JITTER_DURATION);
2122         }
2123     }
2124     else if (iRenderingSkew < (int32)iIncomingSkew)
2125     {
2126         skewDelta = iIncomingSkew - iRenderingSkew;
2127         if (iMediaType.isCompressed() && iMediaType.isAudio())
2128         {
2129             aTSOffset = (PVMFTimestamp)(iAudioLatency + PARSING_JITTER_DURATION + skewDelta);
2130         }
2131         else if (iMediaType.isCompressed() && iMediaType.isVideo())
2132         {
2133             aTSOffset = (PVMFTimestamp)(iVideoLatency + PARSING_JITTER_DURATION);
2134         }
2135     }
2136     aTSOffset += iCurTimestamp;
2137 }
2138 
2139 
2140