| /* ------------------------------------------------------------------ |
| * Copyright (C) 1998-2009 PacketVideo |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either |
| * express or implied. |
| * See the License for the specific language governing permissions |
| * and limitations under the License. |
| * ------------------------------------------------------------------- |
| */ |
| #include "adaptationlayer.h" |
| #define SREJ 0 |
| #define DRTX 255 |
| #define PV2WAY_H223_AL2_SN_WRAPAROUND 256 |
| #define PV2WAY_H223_AL2_CRC_SIZE 1 |
| #define PV2WAY_H223_AL3_CRC_SIZE 2 |
| #define PV2WAY_MAX_PACKET_MEM_FRAG 32 |
| #define PV2WAY_H223_AL2_MAX_HDR_TRLR_FRAG_SIZE 4 |
| #define PV2WAY_H223_AL3_SNPOS1_BITLEN 7 |
| #define PV2WAY_H223_AL3_SNPOS1_VRMAX 0x7F |
| #define PV2WAY_H223_AL3_SNPOS2_VRMAX 0x7FFF |
| #define PV2WAY_H223_AL3_SNPOS2_PT_LEN 1 |
| |
| |
| void AdaptationLayer1::Construct() |
| { |
| iLogger = PVLogger::GetLoggerObject("3g324m.h223.AdaptationLayer1"); |
| } |
| |
| void AdaptationLayer1::ParsePacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt, IncomingALPduInfo& info) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer1::ParsePacket, pdu_size(%d)", pkt->getFilledSize())); |
| oscl_memset(&info, 0, sizeof(IncomingALPduInfo)); |
| info.sdu_size = (int16)pkt->getFilledSize(); |
| |
| } |
| |
| |
| PVMFStatus AdaptationLayer1::CompletePacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt) |
| { |
| OSCL_UNUSED_ARG(pkt); |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer1::CompletePacket packet size(%d)", pkt->getFilledSize())); |
| return PVMFSuccess; |
| } |
| |
| void AdaptationLayer2::Construct() |
| { |
| iLogger = PVLogger::GetLoggerObject("3g324m.h223.AdaptationLayer2"); |
| // Do not Leave on allocation failure |
| iMemFragmentAlloc.SetLeaveOnAllocFailure(false); |
| iMemFragmentAlloc.size((uint16)iMaxNumSdus, PV2WAY_H223_AL2_MAX_HDR_TRLR_FRAG_SIZE); |
| } |
| |
| void AdaptationLayer2::SetSeqnum(bool on_off) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer2::SetSeqnum(%d)", on_off)); |
| if (on_off) |
| { |
| iSNPos = 1; |
| iHdrSz = 1; |
| } |
| else |
| { |
| iSNPos = 0; |
| iHdrSz = 0; |
| } |
| } |
| |
| PVMFStatus AdaptationLayer2::StartPacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt) |
| { |
| if (iSNPos) |
| { |
| OsclRefCounterMemFrag hdr_frag = iMemFragmentAlloc.get(); |
| if (hdr_frag.getMemFragPtr() == NULL) |
| { |
| return PVMFErrNoMemory; |
| } |
| hdr_frag.getMemFrag().len = 1; |
| pkt->appendMediaFragment(hdr_frag); |
| } |
| return PVMFSuccess; |
| } |
| |
| |
| |
| PVMFStatus AdaptationLayer2::CompletePacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt) |
| { |
| int Size = pkt->getFilledSize(); |
| uint8 Crc; |
| uint8* pos = NULL; |
| OsclRefCounterMemFrag hdr_frag; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer2::CompletePacket packet, size(%d)", Size)); |
| |
| OsclRefCounterMemFrag trlr_frag = iMemFragmentAlloc.get(); |
| if (trlr_frag.getMemFragPtr() == NULL) |
| { |
| return PVMFErrNoMemory; |
| } |
| trlr_frag.getMemFrag().len = 1; |
| |
| if (iSNPos) |
| { |
| pkt->getMediaFragment(0, hdr_frag); |
| Size += iSNPos; |
| pos = (uint8*)hdr_frag.getMemFragPtr(); |
| *pos = (uint8)(iSeqNum); |
| if (iSeqNum != 0xff) |
| iSeqNum ++; |
| else |
| iSeqNum = 0; |
| } |
| |
| Crc = crc.Crc8Check(pkt); |
| pkt->appendMediaFragment(trlr_frag); |
| pos = (uint8*)trlr_frag.getMemFragPtr(); |
| |
| *pos = Crc; |
| Size ++; |
| |
| return PVMFSuccess; |
| } |
| |
| #define WINSIZE 10 |
| |
| void AdaptationLayer2::ParsePacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt, IncomingALPduInfo& info) |
| { |
| OsclRefCounterMemFrag frag; |
| uint8 Crc = 0; |
| info.crc_error = false; // No CRC error. |
| info.seq_num_error = 0; // No sequence number error. |
| uint8 SeqNum = 0; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer2::ParsePacket pdu size(%d)", pkt->getFilledSize())); |
| info.sdu_size = (uint16)(pkt->getFilledSize() - iSNPos - PV2WAY_H223_AL2_CRC_SIZE); |
| if (info.sdu_size <= 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "AdaptationLayer2::ParsePacket sdu size(%d) < 0", info.sdu_size)); |
| return; |
| } |
| OsclRefCounterMemFrag last_frag; |
| pkt->getMediaFragment(pkt->getNumFragments() - 1, last_frag); |
| Crc = *((uint8*)last_frag.getMemFragPtr() + last_frag.getMemFragSize() - 1); |
| pkt->setMediaFragFilledLen(pkt->getNumFragments() - 1, last_frag.getMemFrag().len - PV2WAY_H223_AL2_CRC_SIZE); |
| |
| OsclRefCounterMemFrag first_frag; |
| pkt->getMediaFragment(0, first_frag); |
| |
| uint16 CrcCheck = crc.Crc8Check(pkt, false); |
| if (Crc != CrcCheck) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "AdaptationLayer2::ParsePacket CRC error sn(%d)", iSeqNum)); |
| info.crc_error = true; |
| //Update expected sequence number. |
| iSeqNum = (iSeqNum + 1) % PV2WAY_H223_AL2_SN_WRAPAROUND; |
| } |
| else |
| { |
| if (iSNPos == 1) |
| { |
| SeqNum = *((uint8*)first_frag.getMemFragPtr()); |
| first_frag.getMemFrag().len -= iSNPos; |
| first_frag.getMemFrag().ptr = (uint8*)first_frag.getMemFrag().ptr + iSNPos; |
| |
| //If sequence number is good. |
| if (iSeqNum == SeqNum) |
| { |
| iSeqNum = (iSeqNum + 1) % PV2WAY_H223_AL2_SN_WRAPAROUND; |
| } |
| //Else sequence number is not good. |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "AdaptationLayer2::ParsePacket Sequence number error expected(%d), received(%d)", iSeqNum, SeqNum)); |
| |
| //Check the difference between expected seq number and actual seq number. |
| |
| //Check if sequence number wrapped. |
| if (iSeqNum > SeqNum) |
| { |
| info.seq_num_error = (PV2WAY_H223_AL2_SN_WRAPAROUND - iSeqNum) + SeqNum; |
| } |
| //Else no wrap. |
| { |
| info.seq_num_error = SeqNum - iSeqNum; |
| } |
| |
| //Update expected seq number based on actual seq number received. |
| iSeqNum = (SeqNum + 1) % PV2WAY_H223_AL2_SN_WRAPAROUND; |
| } |
| } |
| } |
| if (iSNPos) |
| { |
| OsclRefCounterMemFrag frags[PV2WAY_MAX_PACKET_MEM_FRAG]; |
| unsigned int num_frags = pkt->getNumFragments(); |
| if (num_frags <= PV2WAY_MAX_PACKET_MEM_FRAG) |
| { |
| unsigned int fragnum; |
| frags[0] = first_frag; |
| for (fragnum = 1;fragnum < num_frags;fragnum++) |
| { |
| pkt->getMediaFragment(fragnum, frags[fragnum]); |
| } |
| pkt->clearMediaFragments(); |
| for (fragnum = 0;fragnum < num_frags;fragnum++) |
| { |
| pkt->appendMediaFragment(frags[fragnum]); |
| } |
| } |
| else |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer2::ParsePacket pkt->getNumFragments() is greater then PV2WAY_MAX_PACKET_MEM_FRAG")); |
| } |
| } |
| } |
| |
| void AdaptationLayer3::Construct() |
| { |
| iLogger = PVLogger::GetLoggerObject("3g324m.h223.AdaptationLayer3"); |
| // Do not Leave on allocation failure |
| iMemFragmentAlloc.SetLeaveOnAllocFailure(false); |
| iMemFragmentAlloc.size((uint16)(iMaxNumSdus*2), 4); |
| } |
| |
| void AdaptationLayer3::SetSeqnumSz(uint16 sz) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer3::SetSeqnumSz(%d)", sz)); |
| iSNPos = sz; |
| iHdrSz = sz; |
| } |
| |
| PVMFStatus AdaptationLayer3::StartPacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt) |
| { |
| if (iSNPos) |
| { |
| OsclRefCounterMemFrag hdr_frag = iMemFragmentAlloc.get(); |
| if (hdr_frag.getMemFragPtr() == NULL) |
| { |
| return PVMFErrNoMemory; |
| } |
| hdr_frag.getMemFrag().len = iSNPos; |
| pkt->appendMediaFragment(hdr_frag); |
| } |
| return PVMFSuccess; |
| } |
| |
| PVMFStatus AdaptationLayer3::CompletePacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt) |
| { |
| int Size = pkt->getFilledSize(); |
| unsigned Crc = 0, usTmp = 0; |
| uint8* pos = NULL; |
| OsclRefCounterMemFrag hdr_frag; |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer3::CompletePacket(%d)", pkt->getFilledSize())); |
| OsclRefCounterMemFrag trlr_frag = iMemFragmentAlloc.get(); |
| if (trlr_frag.getMemFragPtr() == NULL) |
| { |
| return PVMFErrNoMemory; |
| } |
| |
| trlr_frag.getMemFrag().len = 2; |
| Size += iSNPos; |
| |
| switch (iSNPos) |
| { |
| case 0: |
| break; |
| case 1: |
| usTmp = (uint16)iSeqNum; |
| pkt->getMediaFragment(0, hdr_frag); |
| pos = (uint8*)hdr_frag.getMemFragPtr(); |
| |
| *pos = (uint8)((usTmp << 1) | 1); |
| if (usTmp != PV2WAY_H223_AL3_SNPOS1_VRMAX) |
| iSeqNum ++; |
| else |
| iSeqNum = 0; |
| break; /* SN( 7bit ) */ |
| case 2: |
| usTmp = iSeqNum; |
| pkt->getMediaFragment(0, hdr_frag); |
| pos = (uint8*)hdr_frag.getMemFragPtr(); |
| |
| *pos = (uint8)((usTmp >> 7) | 1); |
| *(pos + 1) = (uint8)(usTmp & 0xff); |
| if (usTmp != PV2WAY_H223_AL3_SNPOS2_VRMAX) |
| iSeqNum ++; |
| else |
| iSeqNum = 0; |
| break; /* SN( 15bit )*/ |
| } |
| |
| Crc = crc.Crc16Check(pkt); |
| pkt->appendMediaFragment(trlr_frag); |
| pos = (uint8*)trlr_frag.getMemFragPtr(); |
| |
| *(pos) = (uint8)(Crc & 0xff); |
| *(pos + 1) = (uint8)(Crc >> 8); |
| Size += 2; |
| return PVMFSuccess; |
| } |
| |
| #define WINSIZE 10 |
| |
| void AdaptationLayer3::ParsePacket(OsclSharedPtr<PVMFMediaDataImpl>& pkt, IncomingALPduInfo& info) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_STACK_TRACE, (0, "AdaptationLayer3::ParsePacket pdu_size(%d)", pkt->getFilledSize())); |
| OsclRefCounterMemFrag frag; |
| uint16 SeqNum = 0; |
| uint16 Crc = 0, VrMax = 0; |
| iPktNum++; |
| info.crc_error = false; |
| info.seq_num_error = 0; |
| info.sdu_size = (uint16)(pkt->getFilledSize() - iSNPos - PV2WAY_H223_AL3_CRC_SIZE); |
| if (info.sdu_size <= 0) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "AdaptationLayer3::ParsePacket sdu size(%d) < 0", info.sdu_size)); |
| return; |
| } |
| |
| OsclRefCounterMemFrag first_frag, last_frag; |
| pkt->getMediaFragment(0, first_frag); |
| pkt->getMediaFragment(pkt->getNumFragments() - 1, last_frag); |
| |
| switch (iSNPos) |
| { |
| case 0: |
| // not used currently |
| break; |
| case 1: |
| SeqNum = (uint16)(((uint8*)first_frag.getMemFragPtr())[0] >> (sizeof(uint8))); |
| VrMax = PV2WAY_H223_AL3_SNPOS1_VRMAX; /* 0-127 */ |
| break; |
| case 2: |
| SeqNum = (uint16)((((uint8*)first_frag.getMemFragPtr())[0] >> 1) << 8 | ((uint8*)first_frag.getMemFragPtr())[1]); |
| VrMax = PV2WAY_H223_AL3_SNPOS2_VRMAX; /* 0-32767 */ |
| break; |
| } |
| |
| if (last_frag.getMemFragSize() >= PV2WAY_H223_AL3_CRC_SIZE) |
| { |
| Crc = (uint16)(((*((uint8*)last_frag.getMemFragPtr() + last_frag.getMemFragSize() - 1)) << 8) | |
| (*((uint8*)last_frag.getMemFragPtr() + last_frag.getMemFragSize() - 2))); |
| pkt->setMediaFragFilledLen(pkt->getNumFragments() - 1, last_frag.getMemFrag().len - PV2WAY_H223_AL3_CRC_SIZE); |
| } |
| else // in the rare case that the last fragment contains only 1 byte of the CRC |
| { |
| OsclRefCounterMemFrag second_last_frag; |
| pkt->getMediaFragment(pkt->getNumFragments() - 2, second_last_frag); |
| Crc = (uint16)(((*((uint8*)last_frag.getMemFragPtr())) << 8) | |
| (*((uint8*)second_last_frag.getMemFragPtr() + second_last_frag.getMemFragSize() - 1))); |
| pkt->setMediaFragFilledLen(pkt->getNumFragments() - 1, last_frag.getMemFrag().len - 1); |
| pkt->setMediaFragFilledLen(pkt->getNumFragments() - 2, second_last_frag.getMemFrag().len - 1); |
| } |
| if (Crc != crc.Crc16Check(pkt, false)) |
| { |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "AdaptationLayer3::ParsePacket CRC error, sn(%d)", iSeqNum)); |
| |
| info.crc_error = true; |
| |
| //Update sequence number. |
| if (iSeqNum == VrMax) |
| { |
| iSeqNum = 0; |
| } |
| else |
| { |
| iSeqNum++; |
| } |
| } |
| else |
| { |
| //If sequence number is good. |
| if (iSeqNum == SeqNum) |
| { |
| if (iSeqNum == VrMax) |
| { |
| iSeqNum = 0; |
| } |
| else |
| { |
| iSeqNum++; |
| } |
| } |
| //Else sequence number is not good. |
| else |
| { /* missing or mis-delivered packets, send them anyway */ |
| PVLOGGER_LOGMSG(PVLOGMSG_INST_HLDBG, iLogger, PVLOGMSG_WARNING, (0, "AdaptationLayer3::ParsePacket Sequence number error - Expected(%d), Received(%d)", iSeqNum, SeqNum)); |
| //Check the difference between expected seq number and actual seq number. |
| |
| //Check if sequence number wrapped. |
| if (iSeqNum > SeqNum) |
| { |
| info.seq_num_error = ((VrMax + 1) - iSeqNum) + SeqNum; |
| } |
| //Else no wrap. |
| { |
| info.seq_num_error = SeqNum - iSeqNum; |
| } |
| |
| //Update |
| iSeqNum = (uint16)((SeqNum + 1) % (VrMax + 1)); |
| } |
| } |
| |
| if (iSNPos) |
| { |
| pkt->getMediaFragment(0, first_frag);// do this in case first frag == last frag |
| first_frag.getMemFrag().len -= iSNPos; |
| first_frag.getMemFrag().ptr = (uint8*)first_frag.getMemFrag().ptr + iSNPos; |
| OsclRefCounterMemFrag frags[PV2WAY_MAX_PACKET_MEM_FRAG]; |
| unsigned int num_frags = pkt->getNumFragments(); |
| unsigned int fragnum; |
| frags[0] = first_frag; |
| for (fragnum = 1;fragnum < num_frags;fragnum++) |
| { |
| pkt->getMediaFragment(fragnum, frags[fragnum]); |
| } |
| pkt->clearMediaFragments(); |
| for (fragnum = 0;fragnum < num_frags;fragnum++) |
| { |
| pkt->appendMediaFragment(frags[fragnum]); |
| } |
| } |
| |
| } |