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

📄 rtp_transmitter.cpp

📁 网络MPEG4IP流媒体开发源代码
💻 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"//#define RTP_DEBUG 1CRtpTransmitter::CRtpTransmitter (CLiveConfig *pConfig) : CMediaSink(){  SetConfig(pConfig);  m_destListMutex = SDL_CreateMutex();  m_audioSrcPort = 0;  m_videoSrcPort = 0;  m_audioRtpDestination = NULL;  m_audioPayloadNumber = 97;  m_audioQueue = NULL;  m_haveAudioStartTimestamp = false;  m_audio_rtp_userdata = NULL;  m_audio_set_rtp_payload = NULL;	// plugin function to determind how to build RTP payload  m_audio_queue_frame = NULL;		// plugin function to determind how to queue frames for RTP  m_frameno = NULL;			// plugin will allocate counter space  m_audioiovMaxCount = 0;		// Max number of iov segments for send_iov  if (m_pConfig->GetBoolValue(CONFIG_AUDIO_ENABLE)) {	      if (m_audioSrcPort == 0) {      m_audioSrcPort = GetRandomPortBlock();    }    if (m_pConfig->GetIntegerValue(CONFIG_RTP_AUDIO_DEST_PORT) == 0) {      m_pConfig->SetIntegerValue(CONFIG_RTP_AUDIO_DEST_PORT,				 m_audioSrcPort + 2);    }    if (get_audio_rtp_info(m_pConfig,			   &m_audioFrameType,			   &m_audioTimeScale,			   &m_audioPayloadNumber, 			   &m_audioPayloadBytesPerPacket,			   &m_audioPayloadBytesPerFrame,			   &m_audioQueueMaxCount,			   &m_audioiovMaxCount,			   &m_audio_queue_frame,			   &m_audio_set_rtp_payload,			   &m_audio_set_rtp_header,			   &m_audio_set_rtp_jumbo_frame,			   &m_audio_rtp_userdata) == false) {      error_message("rtp transmitter: unknown audio encoding %s",		    m_pConfig->GetStringValue(CONFIG_AUDIO_ENCODING));    }    if (m_audioiovMaxCount == 0)			// This is purely for backwards compability      m_audioiovMaxCount = m_audioQueueMaxCount;	// Can go away when lame and faac plugin sets this    if (m_pConfig->GetBoolValue(CONFIG_RTP_DISABLE_TS_OFFSET)) {      m_audioRtpTimestampOffset = 0;    } else {      m_audioRtpTimestampOffset = random();    }    m_audioQueueCount = 0;    m_audioQueueSize = 0;        m_audioQueue = (CMediaFrame**)Malloc(m_audioQueueMaxCount * sizeof(CMediaFrame*));  }  // Initialize Video portion of transmitter  m_videoRtpDestination = NULL;  m_videoPayloadNumber = 96;  m_videoTimeScale = 90000;  m_haveVideoStartTimestamp = false;  if (m_pConfig->GetBoolValue(CONFIG_VIDEO_ENABLE)) {    if (m_pConfig->GetBoolValue(CONFIG_RTP_DISABLE_TS_OFFSET)) {      m_videoRtpTimestampOffset = 0;    } else {      m_videoRtpTimestampOffset = random();    }    if (m_videoSrcPort == 0) {      m_videoSrcPort = GetRandomPortBlock();    }    if (m_pConfig->GetIntegerValue(CONFIG_RTP_VIDEO_DEST_PORT) == 0) {      m_pConfig->SetIntegerValue(CONFIG_RTP_VIDEO_DEST_PORT,				 m_videoSrcPort + 2);    }  }  }CRtpTransmitter::~CRtpTransmitter (void){  CRtpDestination *p;  p = m_audioRtpDestination;  while (p != NULL) {    p = p->get_next();    delete m_audioRtpDestination;    m_audioRtpDestination = p;  }  p = m_videoRtpDestination;  while (p != NULL) {    p = p->get_next();    delete m_videoRtpDestination;    m_videoRtpDestination = p;  }  SDL_DestroyMutex(m_destListMutex);  CHECK_AND_FREE(m_audio_rtp_userdata);  if (m_frameno != NULL) {	free (m_frameno);	m_frameno = NULL;		// Not strictly necessary  }}void CRtpTransmitter::CreateAudioRtpDestination (uint32_t ref,						 char *destAddress,						 in_port_t destPort,						 in_port_t srcPort){  CRtpDestination *adest, *p;  debug_message("Creating rtp destination %s %d %d %d", 		destAddress, destPort, ref, srcPort);  if (srcPort == 0) srcPort = m_audioSrcPort;  adest = new CRtpDestination(ref, 			      destAddress,			      destPort,			      srcPort,			      m_audioPayloadNumber,			      m_pConfig->GetIntegerValue(CONFIG_RTP_MCAST_TTL),			      DEFAULT_RTCP_BW);  SDL_LockMutex(m_destListMutex);  if (m_audioRtpDestination == NULL) {    m_audioRtpDestination = adest;  } else {    p = m_audioRtpDestination;    while (p->get_next() != NULL) {      p = p->get_next();    }    p->set_next(adest);  }  SDL_UnlockMutex(m_destListMutex);}void CRtpTransmitter::CreateVideoRtpDestination (uint32_t ref,						 char *destAddress,						 in_port_t destPort,						 in_port_t srcPort){  CRtpDestination *vdest, *p;  if (srcPort == 0) srcPort = m_audioSrcPort;  vdest = new CRtpDestination(ref, 			      destAddress,			      destPort,			      srcPort,			      m_videoPayloadNumber,			      m_pConfig->GetIntegerValue(CONFIG_RTP_MCAST_TTL),			      DEFAULT_RTCP_BW);  SDL_LockMutex(m_destListMutex);  if (m_videoRtpDestination == NULL) {    m_videoRtpDestination = vdest;  } else {    p = m_videoRtpDestination;    while (p->get_next() != NULL) {      p = p->get_next();    }    p->set_next(vdest);  }  SDL_UnlockMutex(m_destListMutex);}int CRtpTransmitter::ThreadMain(void) {  while (SDL_SemWait(m_myMsgQueueSemaphore) == 0) {    CMsg* pMsg = m_myMsgQueue.get_message();    if (pMsg != NULL) {      switch (pMsg->get_value()) {      case MSG_NODE_STOP_THREAD:	DoStopTransmit();	delete pMsg;	return 0;      case MSG_NODE_START:	DoStartTransmit();	break;      case MSG_NODE_STOP:	DoStopTransmit();	break;      case MSG_SINK_FRAME:	size_t dontcare;	DoSendFrame((CMediaFrame*)pMsg->get_message(dontcare));	break;      case MSG_RTP_DEST_START:	DoStartRtpDestination(pMsg->get_param());	break;      case MSG_RTP_DEST_STOP:	DoStopRtpDestination(pMsg->get_param());	break;      }            delete pMsg;    }  }    return -1;}void CRtpTransmitter::DoStartTransmit(){  if (m_sink) {    return;  }  if (m_audioRtpDestination != NULL) {    m_audioRtpDestination->start();  }  if (m_videoRtpDestination != NULL) {    m_videoRtpDestination->start();  }  if (m_audioRtpDestination || m_videoRtpDestination) {    // automatic sdp file generation    GenerateSdpFile(m_pConfig);    m_sink = true;  }}void CRtpTransmitter::DoStopTransmit(){	if (!m_sink) {		return;	}	if (m_audioRtpDestination) {	  // send any pending frames	  SendQueuedAudioFrames();	  delete m_audioRtpDestination;	  m_audioRtpDestination = NULL;	  free(m_audioQueue);	  m_audioQueue = NULL;	}	if (m_videoRtpDestination) {	  delete m_videoRtpDestination;	  m_videoRtpDestination = NULL;	}	m_sink = false;}void CRtpTransmitter::DoSendFrame(CMediaFrame* pFrame){	if (pFrame == NULL) {		return;	}	if (!m_sink) {	  if (pFrame->RemoveReference())		delete pFrame;	  return;	}	if (pFrame->GetType() == m_audioFrameType && m_audioRtpDestination) {		SendAudioFrame(pFrame);	} else if (pFrame->GetType() == MPEG4VIDEOFRAME 	  && m_videoRtpDestination) {		SendMpeg4VideoWith3016(pFrame);	} else {	  if (pFrame->RemoveReference())		delete pFrame;	}}// void CRtpTransmitter::SendAudioFrame(CMediaFrame* pFrame)void CRtpTransmitter::OldSendAudioFrame(CMediaFrame* pFrame){	// 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;	  int32_t diff;	  ourTs = AudioTimestampToRtp(pFrame->GetTimestamp());	  diff = ourTs - m_nextAudioRtpTimestamp;	  if (diff > 1) {	    debug_message("Timestamp not consectutive error - timestamp %llu should be %u is %u", 			  pFrame->GetTimestamp(),			  ourTs, m_nextAudioRtpTimestamp);	    SendQueuedAudioFrames();	    newAudioQueueSize = m_audioQueueSize +=	      m_audioPayloadBytesPerPacket;	  }	}	m_nextAudioRtpTimestamp = 	  AudioTimestampToRtp(pFrame->GetTimestamp()) + 	  pFrame->GetDuration();	newAudioQueueSize +=		m_audioPayloadBytesPerFrame		+ pFrame->GetDataLength();	// if new queue size exceeds the RTP payload	if (newAudioQueueSize 	  > m_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE)) {		// 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_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE)) {		// 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 CRtpTransmitter::SendAudioFrame(CMediaFrame* pFrame){	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_pConfig->GetIntegerValue(CONFIG_RTP_PAYLOAD_SIZE));#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");

⌨️ 快捷键说明

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