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