📄 lid.cxx
字号:
} SetCountryCode(UnknownCountry); return FALSE;}PString OpalLineInterfaceDevice::GetErrorText() const{ return PChannel::GetErrorText(PChannel::Miscellaneous, osError);}void OpalLineInterfaceDevice::PrintOn(ostream & strm) const{ strm << GetName();}/////////////////////////////////////////////////////////////////////////////OpalLineChannel::OpalLineChannel(OpalLineInterfaceDevice & dev, unsigned line, BOOL rd) : device(dev){ lineNumber = line; reading = rd; codec = RTP_DataFrame::L16_Mono; if (reading) { device.SetReadCodec(line, codec); deblockingBuffer.SetSize(device.GetReadFrameSize(lineNumber)); deblockingOffset = P_MAX_INDEX; } else { device.SetWriteCodec(line, codec); deblockingBuffer.SetSize(device.GetWriteFrameSize(lineNumber)); deblockingOffset = 0; }}OpalLineChannel::~OpalLineChannel(){ Close();}PString OpalLineChannel::GetName() const{ return device.GetName() + psprintf("-%u", lineNumber);}BOOL OpalLineChannel::Close(){ if (reading) return device.StopReadCodec(lineNumber); else return device.StopWriteCodec(lineNumber);}BOOL OpalLineChannel::SetCodec(RTP_DataFrame::PayloadTypes theCodec){ codec = theCodec; if (reading) { if (!device.SetReadCodec(lineNumber, codec)) return FALSE; } else { if (!device.SetWriteCodec(lineNumber, codec)) return FALSE; } PTRACE(3, "LID\tCodec set to " << theCodec << ", frame size=" << device.GetReadFrameSize(lineNumber) << '/' << device.GetWriteFrameSize(lineNumber)); return TRUE;}BOOL OpalLineChannel::ReadFrame(BYTE * buffer){ if (device.ReadFrame(lineNumber, buffer)) return TRUE;#if PTRACING if (device.GetErrorNumber() != 0) PTRACE(1, "LID\tDevice read frame error: " << device.GetErrorText());#endif return FALSE;}BOOL OpalLineChannel::Read(void * buffer, PINDEX length){ if (!reading) { lastError = Miscellaneous; osError = EINVAL; return FALSE; } BYTE * bufferPtr = (BYTE *)buffer; // Pick out special cases for G.723.1 based codecs (variable length frames) if (codec == RTP_DataFrame::G7231) { if (!ReadFrame(bufferPtr)) return FALSE; switch (bufferPtr[0]&3) { case 0 : // 6.3kbps rate frame lastReadCount = 24; break; case 1 : // 5.3kbps rate frame lastReadCount = 20; break; case 2 : // a Silence Insertion Descriptor lastReadCount = 4; break; case 3 : // repeat last CNG frame lastReadCount = 0; break; } return TRUE; } // Are reblocking the hardware frame sizes to those expected by the RTP packets. lastReadCount = 0; device.SetReadFrameSize(lineNumber, length); PINDEX frameSize = device.GetReadFrameSize(lineNumber); while (length > 0) { if (deblockingOffset < frameSize) { PINDEX left = frameSize - deblockingOffset; if (left > length) left = length; memcpy(bufferPtr, &deblockingBuffer[deblockingOffset], left); lastReadCount += left; deblockingOffset += left; bufferPtr += left; length -= left; } else if (length < frameSize) { BYTE * deblockPtr = deblockingBuffer.GetPointer(frameSize); if (!ReadFrame(deblockPtr)) return FALSE; deblockingOffset = 0;#ifdef CISCO_G728_HACK if (codec == RTP_DataFrame::G728) swab((char *)deblockPtr, (char *)deblockPtr, frameSize);#endif } else { if (!ReadFrame(bufferPtr)) return FALSE;#ifdef CISCO_G728_HACK if (codec == RTP_DataFrame::G728) swab((char *)bufferPtr, (char *)bufferPtr, frameSize);#endif lastReadCount += frameSize; bufferPtr += frameSize; length -= frameSize; } } return TRUE;}BOOL OpalLineChannel::WriteFrame(const BYTE * buffer){ if (device.WriteFrame(lineNumber, buffer)) return TRUE;#if PTRACING if (device.GetErrorNumber() != 0) PTRACE(1, "LID\tDevice write frame error: " << device.GetErrorText());#endif return FALSE;}BOOL OpalLineChannel::Write(const void * buffer, PINDEX length){ if (reading) { lastError = Miscellaneous; osError = EINVAL; return FALSE; } device.SetWriteFrameSize(lineNumber, length); PINDEX frameSize = device.GetWriteFrameSize(lineNumber); // Check for writing silence if (length == 0) { deblockingOffset = 0; // Throw away any partial data lastWriteCount = 0; static const BYTE g723_sid_frame[24] = { 2 }; static const BYTE g729_cng_frame[10] = { 0 }; // What is this? switch (codec) { case RTP_DataFrame::G7231 : return WriteFrame(g723_sid_frame); case RTP_DataFrame::G729 : return WriteFrame(g729_cng_frame); case RTP_DataFrame::PCMU: case RTP_DataFrame::PCMA: memset(deblockingBuffer.GetPointer(frameSize), 0x80, frameSize); break; default : memset(deblockingBuffer.GetPointer(frameSize), 0, frameSize); break; } return WriteFrame(deblockingBuffer); } /* The outer logical channel processing will automatically increment through the packet buffer by the value of lastWriteCount bytes. So even if length is set to 80 bytes for G.723.1 say, returning 24 will cause this function to be called again (in 30 milliseconds in the G.723.1 case) with len set to 56 and the buf pointer incremented 24 bytes. */ const BYTE * bufferPtr = (const BYTE *)buffer; if (codec == RTP_DataFrame::G7231) { // Pick out special cases for G.723.1 based codec (variable length frames) switch (bufferPtr[0]&3) { case 0 : // 6.3kbps rate frame lastWriteCount = 24; break; case 1 : // 5.3kbps rate frame lastWriteCount = 20; break; case 2 : // a Silence Insertion Descriptor lastWriteCount = 4; break; case 3 : // repeat last CNG frame lastWriteCount = 1; break; } return WriteFrame(bufferPtr); } // Are reblocking output frame sizes to those expected by codec hardware. lastWriteCount = 0; while (length > 0) { // If have enough data and nothing in the reblocking buffer, just send it // straight on to the device. if (deblockingOffset == 0 && length >= frameSize) {#ifdef CISCO_G728_HACK if (codec == RTP_DataFrame::G728) swab((char *)bufferPtr, (char *)bufferPtr, frameSize);#endif if (!WriteFrame(bufferPtr)) return FALSE; lastWriteCount += frameSize; bufferPtr += frameSize; length -= frameSize; } else { BYTE * savedFramePtr = deblockingBuffer.GetPointer(frameSize); // See if new chunk gives us enough for one frames worth if ((deblockingOffset + length) < frameSize) { // Nope, just copy bytes into buffer and return memcpy(savedFramePtr + deblockingOffset, bufferPtr, length); deblockingOffset += length; lastWriteCount += length; return TRUE; } /* Calculate bytes we want from the passed in buffer to fill a frame by subtracting from full frame width the amount we have so far. This also means the lastWriteCount is set to the correct amount of buffer we are grabbing this time around. */ PINDEX left = frameSize - deblockingOffset; memcpy(savedFramePtr + deblockingOffset, bufferPtr, left); deblockingOffset = 0;#ifdef CISCO_G728_HACK if (codec == RTP_DataFrame::G728) swab((char *)bufferPtr, (char *)bufferPtr, frameSize);#endif // Write the saved frame out if (!WriteFrame(savedFramePtr)) return FALSE; lastWriteCount += left; bufferPtr += left; length -= left; } } return TRUE;}///////////////////////////////////////////////////////////////////////////////static struct { const char * description; unsigned bytesPerFrame; unsigned samplesPerFrame; unsigned rxFramesInPacket; unsigned txFramesInPacket; RTP_DataFrame::PayloadTypes payloadType; H245_AudioCapability::Choices capabilitySubtype;} CodecTypeInfo[] = { { "G.711-uLaw-64k{hw}", 8, 8, 240, 30, RTP_DataFrame::PCMU, H245_AudioCapability::e_g711Ulaw64k }, { "G.711-ALaw-64k{hw}", 8, 8, 240, 30, RTP_DataFrame::PCMA, H245_AudioCapability::e_g711Alaw64k },#ifdef CISCO_G728_HACK { "G.728{hw}", 20, 80, 24, 6, RTP_DataFrame::G728, H245_AudioCapability::e_g728 },#else { "G.728{hw}", 5, 20, 96, 20, RTP_DataFrame::G728, H245_AudioCapability::e_g728 },#endif { "G.729a{hw}", 10, 80, 24, 6, RTP_DataFrame::G729, H245_AudioCapability::e_g729AnnexA }, { "G.723.1{hw}", 24, 240, 8, 3, RTP_DataFrame::G7231, H245_AudioCapability::e_g7231 }, { "GSM-0610{hw}", 33, 160, 7, 4, RTP_DataFrame::GSM, H245_AudioCapability::e_gsmFullRate }};void H323_LIDCapability::AddAllCapabilities(const OpalLineInterfaceDevice & device, H323Capabilities & capabilities, PINDEX descriptorNum, PINDEX simultaneous){ PIntArray codecsAvailable = device.GetPayloadTypes(); for (PINDEX c = 0; c < codecsAvailable.GetSize(); c++) { H323_LIDCapability * cap = new H323_LIDCapability((RTP_DataFrame::PayloadTypes)codecsAvailable[c]); if (cap->IsValid() && !capabilities.FindCapability(cap->GetMainType(), cap->GetSubType())) capabilities.SetCapability(descriptorNum, simultaneous, cap); else delete cap; }}H323_LIDCapability::H323_LIDCapability(RTP_DataFrame::PayloadTypes rtpType) : H323AudioCapability(0, 0){ codecTableIndex = 0; while (IsValid()) { if (CodecTypeInfo[codecTableIndex].payloadType == rtpType) { maxFrameSize = CodecTypeInfo[codecTableIndex].bytesPerFrame; rxFramesInPacket = CodecTypeInfo[codecTableIndex].rxFramesInPacket; txFramesInPacket = CodecTypeInfo[codecTableIndex].txFramesInPacket; break; } codecTableIndex++; }}BOOL H323_LIDCapability::IsValid() const{ return codecTableIndex < PARRAYSIZE(CodecTypeInfo);}PObject * H323_LIDCapability::Clone() const{ return new H323_LIDCapability(*this);}PString H323_LIDCapability::GetFormatName() const{ return CodecTypeInfo[codecTableIndex].description;}unsigned H323_LIDCapability::GetSubType() const{ return CodecTypeInfo[codecTableIndex].capabilitySubtype;}H323Codec * H323_LIDCapability::CreateCodec(H323Codec::Direction direction) const{ return new H323_LIDCodec(direction, direction == H323Codec::Encoder ? txFramesInPacket : rxFramesInPacket, codecTableIndex);}BOOL H323_LIDCapability::OnSendingPDU(H245_AudioCapability & pdu, unsigned packetSize) const{ pdu.SetTag(GetSubType()); switch (pdu.GetTag()) { case H245_AudioCapability::e_gsmFullRate : { H245_GSMAudioCapability & gsm = pdu; gsm.m_audioUnitSize = packetSize*CodecTypeInfo[codecTableIndex].bytesPerFrame; break; } case H245_AudioCapability::e_g7231 : { H245_AudioCapability_g7231 & g7231 = pdu; g7231.m_maxAl_sduAudioFrames = packetSize; g7231.m_silenceSuppression = TRUE; break; } default : { PASN_Integer & value = pdu; value = packetSize; } } return TRUE;}BOOL H323_LIDCapability::OnReceivedPDU(const H245_AudioCapability & pdu, unsigned & packetSize){ if (pdu.GetTag() != GetSubType()) return FALSE; switch (pdu.GetTag()) { case H245_AudioCapability::e_gsmFullRate : { const H245_GSMAudioCapability & gsm = pdu; packetSize = gsm.m_audioUnitSize/CodecTypeInfo[codecTableIndex].bytesPerFrame; break; } case H245_AudioCapability::e_g7231 : { const H245_AudioCapability_g7231 & g7231 = pdu; packetSize = g7231.m_maxAl_sduAudioFrames; break; } default : { const PASN_Integer & value = pdu; packetSize = value; } } return TRUE;}/////////////////////////////////////////////////////////////////////////////H323_LIDCodec::H323_LIDCodec(Direction direction, unsigned numFrames, unsigned index) : H323AudioCodec(direction, CodecTypeInfo[index].samplesPerFrame){ rtpPayloadType = CodecTypeInfo[index].payloadType; codecTableIndex = index; packetSize = CodecTypeInfo[index].bytesPerFrame; /* Special case for G.711 encoder, note this helps with optimisation of sound data but will break if remote does not send the maximum number of bytes that it said it could. It is legal for the remote end to do so though no endpoints seem to actually do that. */ if (packetSize == 8) { packetSize *= numFrames; samplesPerFrame *= numFrames; } PTRACE(3, "LID\tCreated codec: pt=" << rtpPayloadType << ", bytes=" << packetSize << ", samples=" << samplesPerFrame);}BOOL H323_LIDCodec::Open(H323Connection & connection){ if (!H323AudioCodec::Open(connection)) return FALSE; if (rawDataChannel->IsDescendant(OpalLineChannel::Class())) { OpalLineChannel * lineChannel = (OpalLineChannel*)rawDataChannel; if (lineChannel->SetCodec(rtpPayloadType)) return TRUE; PTRACE(1, "LID\tCould not set codec " << rtpPayloadType); return FALSE; } PTRACE(1, "LID\tNo IxJ device set."); return FALSE;}BOOL H323_LIDCodec::Read(BYTE * buffer, unsigned & length, RTP_DataFrame &){ // This reads to an H323_IxJChannel class if (!rawDataChannel->Read(buffer, packetSize)) return FALSE; length = DetectSilence() ? 0 : rawDataChannel->GetLastReadCount(); return TRUE;}BOOL H323_LIDCodec::Write(const BYTE * buffer, unsigned length, const RTP_DataFrame & /*frame*/, unsigned & written){ // This writes to an H323_IxJChannel class if (length > packetSize) length = packetSize; if (!rawDataChannel->Write(buffer, length)) return FALSE; written = rawDataChannel->GetLastWriteCount(); return TRUE;}unsigned H323_LIDCodec::GetBandwidth() const{ return CodecTypeInfo[codecTableIndex].bytesPerFrame*8/3;}unsigned H323_LIDCodec::GetAverageSignalLevel(){ return ((OpalLineChannel*)rawDataChannel)->GetDevice().GetAverageSignalLevel(0);}/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -