📄 channels.cxx
字号:
else PTRACE(3, "LogChan\tOnMiscellaneousCommand: chan=" << number << ", type=" << type.GetTagName());}void H323Channel::OnMiscellaneousIndication(const H245_MiscellaneousIndication_type & type){ if (codec != NULL) codec->OnMiscellaneousIndication(type); else PTRACE(3, "LogChan\tOnMiscellaneousIndication: chan=" << number << ", type=" << type.GetTagName());}void H323Channel::OnJitterIndication(DWORD PTRACE_jitter, int PTRACE_skippedFrameCount, int PTRACE_additionalBuffer){ PTRACE(3, "LogChan\tOnJitterIndication:" " jitter=" << PTRACE_jitter << " skippedFrameCount=" << PTRACE_skippedFrameCount << " additionalBuffer=" << PTRACE_additionalBuffer);}BOOL H323Channel::SetInitialBandwidth(){ if (codec == NULL) codec = capability.CreateCodec(GetDirection() == IsReceiver ? H323Codec::Decoder : H323Codec::Encoder); return SetBandwidthUsed(codec->GetBandwidth());}BOOL H323Channel::SetBandwidthUsed(unsigned bandwidth){ connection.UseBandwidth(bandwidthUsed, FALSE); bandwidthUsed = 0; if (!connection.UseBandwidth(bandwidth, TRUE)) return FALSE; bandwidthUsed = bandwidth; return TRUE;}/////////////////////////////////////////////////////////////////////////////H323UnidirectionalChannel::H323UnidirectionalChannel(H323Connection & conn, const H323Capability & cap, Directions direction) : H323Channel(conn, cap), receiver(direction == IsReceiver){}H323Channel::Directions H323UnidirectionalChannel::GetDirection() const{ return receiver ? IsReceiver : IsTransmitter;}void H323UnidirectionalChannel::Start(){ PThread * thread = new H323LogicalChannelThread(endpoint, *this, receiver); if (receiver) receiveThread = thread; else transmitThread = thread;}/////////////////////////////////////////////////////////////////////////////H323BidirectionalChannel::H323BidirectionalChannel(H323Connection & conn, const H323Capability & cap) : H323Channel(conn, cap){}H323Channel::Directions H323BidirectionalChannel::GetDirection() const{ return IsBidirectional;}void H323BidirectionalChannel::Start(){ receiveThread = new H323LogicalChannelThread(endpoint, *this, TRUE); transmitThread = new H323LogicalChannelThread(endpoint, *this, FALSE);}/////////////////////////////////////////////////////////////////////////////H323_RTPChannel::H323_RTPChannel(H323Connection & conn, const H323Capability & cap, Directions direction, RTP_Session & r) : H323UnidirectionalChannel(conn, cap, direction), rtpSession(r), rtpCallbacks(*(H323_RTP_Session *)r.GetUserData()){ PTRACE(3, "H323RTP\t" << (receiver ? "Receiver" : "Transmitter") << " created using session " << GetSessionID());}H323_RTPChannel::~H323_RTPChannel(){ // Finished with the RTP session, this will delete the session if it is no // longer referenced by any logical channels. connection.ReleaseSession(GetSessionID());}void H323_RTPChannel::CleanUpOnTermination(){ if (terminating) return; PTRACE(3, "H323RTP\tCleaning up RTP " << number); // Break any I/O blocks and wait for the thread that uses this object to // terminate before we allow it to be deleted. rtpSession.Close(receiver); H323Channel::CleanUpOnTermination();}unsigned H323_RTPChannel::GetSessionID() const{ return rtpSession.GetSessionID();}BOOL H323_RTPChannel::OnSendingPDU(H245_OpenLogicalChannel & open) const{ PTRACE(3, "H323RTP\tOnSendingPDU"); open.m_forwardLogicalChannelNumber = (unsigned)number; if (open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) { open.m_reverseLogicalChannelParameters.IncludeOptionalField( H245_OpenLogicalChannel_reverseLogicalChannelParameters::e_multiplexParameters); // Set the communications information for unicast IPv4 open.m_reverseLogicalChannelParameters.m_multiplexParameters.SetTag( H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters ::e_h2250LogicalChannelParameters); return rtpCallbacks.OnSendingPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters, receiver); } else { // Set the communications information for unicast IPv4 open.m_forwardLogicalChannelParameters.m_multiplexParameters.SetTag( H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters ::e_h2250LogicalChannelParameters); return rtpCallbacks.OnSendingPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters, receiver); }}void H323_RTPChannel::OnSendOpenAck(const H245_OpenLogicalChannel & open, H245_OpenLogicalChannelAck & ack) const{ PTRACE(3, "H323RTP\tOnSendOpenAck"); // set forwardMultiplexAckParameters option ack.IncludeOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters); // select H225 choice ack.m_forwardMultiplexAckParameters.SetTag( H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters); // get H225 parms H245_H2250LogicalChannelAckParameters & param = ack.m_forwardMultiplexAckParameters; // set session ID param.IncludeOptionalField(H245_H2250LogicalChannelAckParameters::e_sessionID); const H245_H2250LogicalChannelParameters & openparam = open.m_forwardLogicalChannelParameters.m_multiplexParameters; unsigned sessionID = openparam.m_sessionID; param.m_sessionID = sessionID; rtpCallbacks.OnSendingAckPDU(param); PTRACE(2, "H323RTP\tSending open logical channel ACK: sessionID=" << sessionID);}BOOL H323_RTPChannel::OnReceivedPDU(const H245_OpenLogicalChannel & open, unsigned & errorCode){ if (receiver) number = H323ChannelNumber(open.m_forwardLogicalChannelNumber, TRUE); PTRACE(3, "H323RTP\tOnReceivedPDU for channel: " << number); if (open.HasOptionalField(H245_OpenLogicalChannel::e_reverseLogicalChannelParameters)) { if (open.m_reverseLogicalChannelParameters.m_multiplexParameters.GetTag() == H245_OpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters:: e_h2250LogicalChannelParameters) return rtpCallbacks.OnReceivedPDU(open.m_reverseLogicalChannelParameters.m_multiplexParameters, errorCode); } else { if (open.m_forwardLogicalChannelParameters.m_multiplexParameters.GetTag() == H245_OpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters:: e_h2250LogicalChannelParameters) return rtpCallbacks.OnReceivedPDU(open.m_forwardLogicalChannelParameters.m_multiplexParameters, errorCode); } PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported"); errorCode = H245_OpenLogicalChannelReject_cause::e_unsuitableReverseParameters; return FALSE;}BOOL H323_RTPChannel::OnReceivedAckPDU(const H245_OpenLogicalChannelAck & ack){ PTRACE(3, "H323RTP\tOnReceiveOpenAck"); if (!ack.HasOptionalField(H245_OpenLogicalChannelAck::e_forwardMultiplexAckParameters)) { PTRACE(1, "H323RTP\tNo forwardMultiplexAckParameters"); return FALSE; } if (ack.m_forwardMultiplexAckParameters.GetTag() != H245_OpenLogicalChannelAck_forwardMultiplexAckParameters::e_h2250LogicalChannelAckParameters) { PTRACE(1, "H323RTP\tOnly H.225.0 multiplex supported"); return FALSE; } return rtpCallbacks.OnReceivedAckPDU(ack.m_forwardMultiplexAckParameters);}void H323_RTPChannel::Transmit(){ if (codec == NULL) { PAssertAlways(PLogicError); return; } // Open the codec if (!codec->Open(connection)) { PTRACE(2, "H323RTP\tTransmit thread ended (open fail)"); return; } // Give the connection (or endpoint) a chance to do something with // the opening of the codec. Default calls codec->Open(); if (!connection.OnStartLogicalChannel(*this)) { PTRACE(2, "H323RTP\tTransmit thread ended (OnStartLogicalChannel fail)"); return; } // Get parameters from the codec on time and data sizes unsigned framesInPacket = capability.GetTxFramesInPacket(); unsigned maxFrameSize = capability.GetMaxFrameSize(); RTP_DataFrame frame(framesInPacket*maxFrameSize); frame.SetPayloadType(codec->GetRTPPayloadType()); unsigned codecTimestamps = codec->GetFrameRate(); BOOL isAudio = codec->NeedsJitterBuffer(); PTRACE(2, "H323RTP\tTransmit " << (isAudio ? "audio" : "video") << " thread started:" " rate=" << codecTimestamps << " time=" << (codecTimestamps/codec->GetTimeUnits()) << "ms" " size=" << framesInPacket << '*' << maxFrameSize << '=' << framesInPacket*maxFrameSize); // This is real time so need to keep track of elapsed milliseconds BOOL silent = TRUE; unsigned length; unsigned frameOffset = 0; unsigned frameCount = 0; DWORD rtpTimestamp = 0; // Now keep getting encoded frames from the codec, we make sure we do not // call it any faster than codecMilliseconds, even though as a rule // the function takes exactly codecMilliseconds to complete anyway. while (codec->Read(frame.GetPayloadPtr()+frameOffset, length, frame)) { if (paused) length = 0; // Act as though silent/no video // Handle marker bit for audio codec if (isAudio) { // If switching from silence to signal if (silent && length > 0) { silent = FALSE; frame.SetMarker(TRUE); // Set flag for start of sound PTRACE(3, "H323RTP\tTransmit start of talk burst: " << rtpTimestamp); } // If switching from signal to silence else if (!silent && length == 0) { silent = TRUE; // If had some data waiting to go out if (frameOffset > 0) frameCount = framesInPacket; // Force the RTP write PTRACE(3, "H323RTP\tTransmit end of talk burst: " << rtpTimestamp); } } // Read some data, if (length > 0) { // If first read frame in packet, set timestamp for it if (frameOffset == 0) frame.SetTimestamp(rtpTimestamp); frameOffset += length; // Increment by number of frames that were read in one hit // Note a codec that does variable length frames should never return // more than one frame per Read() call or confusion will result. frameCount += (length + maxFrameSize - 1)/maxFrameSize; } // Have read number of frames for packet (or just went silent) if (frameCount >= framesInPacket) { // Set payload size to frame offset, now length of frame. frame.SetPayloadSize(frameOffset); // Send the frame of coded data we have so far to RTP transport if (!rtpSession.WriteData(frame)) break; // Reset flag for in talk burst if (isAudio) frame.SetMarker(FALSE); frameOffset = 0; frameCount = 0; } // Calculate the timestamp and real time to take in processing rtpTimestamp += codecTimestamps; } if (!terminating) connection.CloseLogicalChannel(number, number.IsFromRemote()); PTRACE(2, "H323RTP\tTransmit thread ended");}void H323_RTPChannel::Receive(){ PTRACE(2, "H323RTP\tReceive thread started"); if (codec == NULL) { PAssertAlways(PLogicError); return; } // Open the codec if (!codec->Open(connection)) { PTRACE(2, "H323RTP\tReceive thread ended (open fail)"); return; } // Give the connection (or endpoint) a chance to do something with // the opening of the codec. Default calls codec->Open(); if (!connection.OnStartLogicalChannel(*this)) { PTRACE(2, "H323RTP\tReceive thread ended (OnStartLogicalChannel fail)"); return; } // if jitter buffer required, start the thread that is on the other end of it BOOL needsDelay = codec->NeedsJitterBuffer(); if (needsDelay) rtpSession.SetJitterBufferSize(endpoint.GetMaxAudioDelayJitter()*codec->GetTimeUnits()); // Keep time using th RTP timestamps. DWORD codecFrameRate = codec->GetFrameRate(); DWORD rtpTimestamp = 0; RTP_DataFrame frame; while (rtpSession.ReadBufferedData(rtpTimestamp, frame)) { int size = frame.GetPayloadSize(); rtpTimestamp = frame.GetTimestamp(); unsigned written; BOOL ok = TRUE; if (size == 0) { ok = codec->Write(NULL, 0, frame, written); rtpTimestamp += codecFrameRate; } else {#if PTRACING // Make sure is from the current payload type for the codec selected if (frame.GetPayloadType() != codec->GetRTPPayloadType()) PTRACE(1, "H323RTP\tPayload type mismatch: expected " << codec->GetRTPPayloadType() << ", got " << frame.GetPayloadType());#endif const BYTE * ptr = frame.GetPayloadPtr(); while (ok && size > 0) { ok = codec->Write(ptr, paused ? 0 : size, frame, written); rtpTimestamp += codecFrameRate; size -= written; ptr += written; }#if PTRACING if (size < 0) PTRACE(1, "H323RTP\tPayload size too small, short " << -size << " bytes.");#endif } if (terminating) break; if (!ok) { connection.CloseLogicalChannel(number, number.IsFromRemote()); break; } } PTRACE(2, "H323RTP\tReceive thread ended");}/////////////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -