⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtp_transmitter.cpp

📁 完整的RTP RTSP代码库
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (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.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is MPEG4IP. *  * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000, 2001.  All Rights Reserved. *  * Contributor(s):  *		Dave Mackie		dmackie@cisco.com *		Bill May 		wmay@cisco.com *		Peter Maersk-Moller	peter@maersk-moller.net */#include "mp4live.h"#include "rtp_transmitter.h"#include "encoder-h261.h"#include "audio_encoder.h"#include "video_encoder.h"#include "text_encoder.h"#include "liblibsrtp.h"//#define RTP_DEBUG 1//#define DEBUG_WRAP_TS 1//#define DEBUG_SEND 1CRtpTransmitter::CRtpTransmitter (uint16_t mtu, bool disable_ts_offset) : CMediaSink(){  //SetConfig(pConfig);  m_destListMutex = SDL_CreateMutex();  m_rtpDestination = NULL;  m_haveStartTimestamp = false;  m_mtu = m_original_mtu = mtu;#ifdef DEBUG_WRAP_TS  m_rtpTimestampOffset = 0xffff0000;#else   if (disable_ts_offset) {    m_rtpTimestampOffset = 0;  } else {    m_rtpTimestampOffset = random();  }#endif  }CRtpTransmitter::~CRtpTransmitter (void){  DoStopTransmit();  SDL_DestroyMutex(m_destListMutex);}void CRtpTransmitter::DoAddRtpDestinationToQueue (CRtpDestination *dest){  CRtpDestination *p;  SDL_LockMutex(m_destListMutex);  if (m_rtpDestination == NULL) {    m_rtpDestination = dest;  } else {    p = m_rtpDestination;    while (p->get_next() != NULL) {      p = p->get_next();    }    p->set_next(dest);  }  SDL_UnlockMutex(m_destListMutex);}void CRtpTransmitter::AddRtpDestination (struct rtp *rtp){  CRtpDestination *dest;  dest = new CRtpDestination(rtp, m_payloadNumber);    m_mtu = m_original_mtu - rtp_get_mtu_adjustment(rtp);  DoAddRtpDestinationToQueue(dest);}  void CRtpTransmitter::AddRtpDestination (mp4live_rtp_params_t *rtp_params){  CRtpDestination *dest;  const char *destAddress = rtp_params->rtp_params.rtp_addr;  in_port_t destPort = rtp_params->rtp_params.rtp_tx_port;  in_port_t srcPort = rtp_params->rtp_params.rtp_rx_port;  uint8_t max_ttl = rtp_params->rtp_params.rtp_ttl;  rtp_params->rtp_params.rtcp_bandwidth = DEFAULT_RTCP_BW;  debug_message("Creating rtp destination %s %u %u: ttl %u", 		destAddress, destPort, srcPort, max_ttl);  /* wmay - comment out for now - might have to revisit for SSM     if (srcPort == 0) srcPort = destPort;   */  dest = m_rtpDestination;  SDL_LockMutex(m_destListMutex);  while (dest != NULL) {    if (dest->Matches(destAddress, destPort)) {      if (srcPort != 0 && srcPort != dest->get_source_port()) {	error_message("Try to create RTP destination to %s:%u with different source ports %u %u",		      destAddress, destPort, srcPort, dest->get_source_port());      } else {	dest->add_reference();	debug_message("adding reference");      }      SDL_UnlockMutex(m_destListMutex);      return;    }    dest = dest->get_next();  }  SDL_UnlockMutex(m_destListMutex);  dest = new CRtpDestination(rtp_params,			     m_payloadNumber);  if (rtp_params->use_srtp && rtp_params->srtp_params.rtp_auth) {    uint16_t diff = m_original_mtu - m_mtu;    if (diff > rtp_params->auth_len) {      m_mtu = m_original_mtu - rtp_params->auth_len;    }  }  DoAddRtpDestinationToQueue(dest);}int CRtpTransmitter::ThreadMain(void) {  CMsg* pMsg;  bool stop = false;  uint32_t len;  while (stop == false && SDL_SemWait(m_myMsgQueueSemaphore) == 0) {    pMsg = m_myMsgQueue.get_message();    if (pMsg != NULL) {      switch (pMsg->get_value()) {      case MSG_NODE_STOP_THREAD:	DoStopTransmit();	stop = true;	break;      case MSG_NODE_START:	DoStartTransmit();	break;      case MSG_NODE_STOP:	DoStopTransmit();	break;      case MSG_SINK_FRAME:	uint32_t dontcare;	DoSendFrame((CMediaFrame*)pMsg->get_message(dontcare));	break;      case MSG_RTP_DEST_START:	DoStartRtpDestination((const char *)pMsg->get_message(len), 			      pMsg->get_param());	break;      case MSG_RTP_DEST_STOP:	DoStopRtpDestination((const char *)pMsg->get_message(len), 			     pMsg->get_param());	break;      }            delete pMsg;    }  }  while ((pMsg = m_myMsgQueue.get_message()) != NULL) {    if (pMsg->get_value() == MSG_SINK_FRAME) {      uint32_t dontcare;      CMediaFrame *mf = (CMediaFrame*)pMsg->get_message(dontcare);      if (mf->RemoveReference()) {	delete mf;      }    }    delete pMsg;  }    return 0;}void CRtpTransmitter::DoStartTransmit(){  if (m_sink) {    return;  }  CRtpDestination *dest = m_rtpDestination;  while (dest != NULL) {    dest->start();    dest = dest->get_next();    m_sink = true;  }}void CRtpTransmitter::DoStopTransmit(){	if (!m_sink) {		return;	}	while (m_rtpDestination != NULL) {	  CRtpDestination *dest = m_rtpDestination;	  m_rtpDestination = dest->get_next();	  delete dest;	}	m_sink = false;}void CAudioRtpTransmitter::DoStopTransmit(void){	// send any pending frames	SendQueuedAudioFrames();	CRtpTransmitter::DoStopTransmit();}void CAudioRtpTransmitter::DoSendFrame(CMediaFrame* pFrame){	if (pFrame == NULL) {		return;	}	if (!m_sink || m_rtpDestination == NULL) {	  if (pFrame->RemoveReference())		delete pFrame;	  return;	}  if (pFrame->GetType() == m_frameType) {    SendAudioFrame(pFrame);  } else {    if (pFrame->RemoveReference())      delete pFrame;  }}void CVideoRtpTransmitter::DoSendFrame (CMediaFrame *pFrame){  if (pFrame == NULL) {    return;  }  if (!m_sink || m_rtpDestination == NULL) {    debug_message("video frame, sink %d dest %p", m_sink, 		  m_rtpDestination);    if (pFrame->RemoveReference())      delete pFrame;    return;  }  if (pFrame->GetType() == m_frameType) {	  // Note - the below changed from the DTS to the PTS - this	  // is required for b-frames, or mpeg2    //debug_message("video rtp has frame");    u_int32_t rtpTimestamp =      TimestampToRtp(pFrame->GetPtsTimestamp());    u_int64_t ntpTimestamp =       TimestampToNtp(pFrame->GetTimestamp());	#ifdef DEBUG_SEND      debug_message("V ts "U64" rtp %u ntp %u.%u",		pFrame->GetTimestamp(),		rtpTimestamp,		(u_int32_t)(ntpTimestamp >> 32),		(u_int32_t)ntpTimestamp);#endif    CRtpDestination *rdptr;	      rdptr = m_rtpDestination;    while (rdptr != NULL) {      rdptr->send_rtcp(rtpTimestamp, ntpTimestamp);      rdptr = rdptr->get_next();    }    (m_videoSendFunc)(pFrame, m_rtpDestination, rtpTimestamp, 		      m_mtu);  } else {    // not the fame we want - okay for previews...    if (pFrame->RemoveReference())      delete pFrame;  }}void CTextRtpTransmitter::DoSendFrame (CMediaFrame *pFrame){  if (pFrame == NULL) {    return;  }  if (!m_sink || m_rtpDestination == NULL) {    debug_message("text frame, sink %d dest %p", m_sink, 		  m_rtpDestination);    if (pFrame->RemoveReference())      delete pFrame;    return;  }  if (pFrame->GetType() == m_frameType) {	  // Note - the below changed from the DTS to the PTS - this	  // is required for b-frames, or mpeg2    //debug_message("video rtp has frame");    u_int32_t rtpTimestamp =      TimestampToRtp(pFrame->GetTimestamp());    u_int64_t ntpTimestamp =       TimestampToNtp(pFrame->GetTimestamp());	      CRtpDestination *rdptr;	      rdptr = m_rtpDestination;    while (rdptr != NULL) {      rdptr->send_rtcp(rtpTimestamp, ntpTimestamp);      rdptr = rdptr->get_next();    }    (m_textSendFunc)(pFrame, m_rtpDestination, rtpTimestamp, 		      m_mtu);  } else {    // not the fame we want - okay for previews...    if (pFrame->RemoveReference())      delete pFrame;  }}// void CRtpTransmitter::SendAudioFrame(CMediaFrame* pFrame)void CAudioRtpTransmitter::OldSendAudioFrame(CMediaFrame* pFrame){  //  debug_message("RTP Timestamp %u\tFrame Duration "U64,  //                AudioTimestampToRtp(pFrame->GetTimestamp())  //                , pFrame->GetDuration());	// first compute how much data we'll have 	// after adding this audio frame	  	//u_int16_t newAudioQueueSize = m_audioQueueSize;        //	if (m_audioQueueCount == 0) {        //		newAudioQueueSize +=         //			m_audioPayloadBytesPerPacket;        //	} else {  //uint32_t ourTs = AudioTimestampToRtp(pFrame->GetTimestamp());  //int32_t diff = ourTs - m_nextAudioRtpTimestamp;  //if (diff > 1) {  //  debug_message("Timestamp not consecutive error - timestamp "U64" should be %u is %u",   //                pFrame->GetTimestamp(),  //                m_nextAudioRtpTimestamp,  //                ourTs);	    //***   SendQueuedAudioFrames();            //	    newAudioQueueSize = m_audioQueueSize +=            //	      m_audioPayloadBytesPerPacket;  //}          //	}  /*	// save the next timestamp.	if (m_audioTimeScale == pFrame->GetDurationScale()) {	  m_nextAudioRtpTimestamp = 	    AudioTimestampToRtp(pFrame->GetTimestamp()) + 	    pFrame->GetDuration();	} else {	  m_nextAudioRtpTimestamp = 	    AudioTimestampToRtp(pFrame->GetTimestamp()) + 	    pFrame->ConvertDuration(m_audioTimeScale);	}  */        uint16_t newAudioQueueSize = m_audioQueueSize          + m_audioPayloadBytesPerPacket          + m_audioPayloadBytesPerFrame          + pFrame->GetDataLength();	// if new queue size exceeds the RTP payload	if (newAudioQueueSize > m_mtu) {		// send anything that's pending		SendQueuedAudioFrames();		// adjust new queue size		newAudioQueueSize =			m_audioPayloadBytesPerPacket			+ m_audioPayloadBytesPerFrame			+ pFrame->GetDataLength();	}	// if new data will fit into RTP payload	if (newAudioQueueSize <= m_mtu) {		// add it to the queue		m_audioQueue[m_audioQueueCount++] = pFrame;		m_audioQueueSize = newAudioQueueSize;		// if we fill the queue, (latency bound)		if (m_audioQueueCount == m_audioQueueMaxCount) {			// send the pending data			SendQueuedAudioFrames();		}	} else {		// highly unusual case 		// we need to fragment audio frame		// over multiple packets		SendAudioJumboFrame(pFrame);	}}/* * #define DROP_IT	1 * #define SEND_FIRST	2 * #define IS_JUMBO	4 * #define SEND_NOW	8 */void CAudioRtpTransmitter::SendAudioFrame(CMediaFrame* pFrame){#ifdef RTP_DEBUG  debug_message("sendaudioframe "U64, pFrame->GetTimestamp());#endif	if (m_audio_queue_frame != NULL) {		// Get status for what we should do with the next frame		int check_frame = m_audio_queue_frame(&m_frameno,			pFrame->GetDataLength(),			m_audioQueueCount, m_audioQueueSize,						      (u_int32_t) m_mtu);#ifdef RTP_DEBUG		fprintf(stderr,"Check Frame :");		if (check_frame & DROP_IT) fprintf(stderr," DROP");		if (check_frame & SEND_FIRST) fprintf(stderr," FIRST");		if (check_frame & IS_JUMBO) fprintf(stderr," JUMBO");		if (check_frame == 0 || !((check_frame & DROP_IT) ||		  (check_frame & IS_JUMBO))) fprintf(stderr," QUEUE");		if (check_frame & SEND_NOW) fprintf(stderr," NOW");		fprintf(stderr,"\n");#endif	// RTP_DEBUG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -