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

📄 text_encoder.cpp

📁 完整的RTP RTSP代码库
💻 CPP
字号:
/* * 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. 2005.  All Rights Reserved. *  * Contributor(s):  *		Bill May wmay@cisco.com */#include "mp4live.h"#include "text_encoder.h"#include "mp4av.h"static config_index_t CFG_TEXT_HREF_BASE_URL;static SConfigVariable hrefEncoderVariables[] = {  CONFIG_STRING(CFG_TEXT_HREF_BASE_URL, "hrefBaseUrl", NULL),};GUI_STRING(gui_href_base, CFG_TEXT_HREF_BASE_URL, "Base Url");DECLARE_TABLE(href_gui_options) = {  TABLE_GUI(gui_href_base),};DECLARE_TABLE_FUNC(href_gui_options);void AddTextProfileEncoderVariables (CTextProfile *pConfig){  pConfig->AddConfigVariables(hrefEncoderVariables, 			      NUM_ELEMENTS_IN_ARRAY(hrefEncoderVariables));}//#define DEBUG_TEXTtext_encoder_table_t text_encoder_table[] = {  { "Plain Text",    TEXT_ENCODING_PLAIN,    NULL,  },  { "ISMA Href",    TEXT_ENCODING_HREF,    TABLE_FUNC(href_gui_options),  }};uint32_t text_encoder_table_size = NUM_ELEMENTS_IN_ARRAY(text_encoder_table);class CPlainTextEncoder : public CTextEncoder { public:  CPlainTextEncoder(CTextProfile *profile, uint16_t mtu, CTextEncoder *next, 		    bool realTime = true) :    CTextEncoder(profile, mtu, next, realTime) { };  bool Init(void) {     m_encodedFrame = NULL;    return true;   };  MediaType GetFrameType(void) { return PLAINTEXTFRAME; }; protected:  void StopEncoder(void) {    CHECK_AND_FREE(m_encodedFrame);  };  bool EncodeFrame (const char *fptr) {    CHECK_AND_FREE(m_encodedFrame);    m_encodedFrame = strdup(fptr);    return true;  };  bool GetEncodedFrame(void **ppBuffer, 		       uint32_t *pBufferLength) {    if (m_encodedFrame == NULL) return false;    *pBufferLength = strlen(m_encodedFrame) + 1;#ifdef DEBUG_TEXT    debug_message("encode len %u", *pBufferLength);#endif    *ppBuffer = strdup(m_encodedFrame);    return true;  };  char *m_encodedFrame;};class CHrefTextEncoder : public CTextEncoder{ public:  CHrefTextEncoder(CTextProfile *profile, uint16_t mtu, CTextEncoder *next, 		    bool realTime = true) :    CTextEncoder(profile, mtu, next, realTime) {   };  bool Init(void) {     m_encodedFrame = NULL;    m_base_url = Profile()->GetStringValue(CFG_TEXT_HREF_BASE_URL);    m_base_url_len = strlen(m_base_url);    return true;   };  MediaType GetFrameType(void) { return HREFTEXTFRAME; }; protected:  void StopEncoder(void) {    CHECK_AND_FREE(m_encodedFrame);  };  void chomp (void) {    char *end = m_encodedFrame + strlen(m_encodedFrame);    end--;    while (isspace(*end)) {      *end = '\0';      end--;    }  }  bool EncodeFrame (const char *fptr) {    ADV_SPACE(fptr);    CHECK_AND_FREE(m_encodedFrame);    if (*fptr == 'A' || *fptr == '<') {      // we have an already formatted href      const char *check = fptr + 1;      if (*check == '<') {	check++;      }      if (strncmp(check, m_base_url, m_base_url_len) == 0) {	check += m_base_url_len;	m_encodedFrame = (char *)malloc(strlen(check) + 					*fptr == 'A' ? 2 : 1);	char *copyto = m_encodedFrame;	if (*fptr == 'A') {	  *copyto++ = 'A';	}	*copyto++ = '<';	strcpy(copyto, check);	debug_message("%s", m_encodedFrame);      } else {	m_encodedFrame = strdup(fptr);      }      chomp();    } else {      // we need to add <> and maybe an A      uint32_t size = strlen(fptr) + 1; // add \0 at end      if (strncmp(fptr, m_base_url, m_base_url_len) == 0) {	fptr += m_base_url_len;      }      debug_message("string \"%s\"", fptr);      size += 2; // add <>      if (Profile()->GetBoolValue(CFG_TEXT_HREF_MAKE_AUTOMATIC)) size++;      m_encodedFrame = (char *)malloc(size);      char *write = m_encodedFrame;      if (Profile()->GetBoolValue(CFG_TEXT_HREF_MAKE_AUTOMATIC)) {	*write++ = 'A';      }      *write++ = '<';      *write = '\0';      strcat(write, fptr);      debug_message("before chomp \"%s\"", m_encodedFrame);      chomp();      strcat(write, ">");      debug_message("\"%s\"", m_encodedFrame);    }    m_encodedFrameLen = strlen(m_encodedFrame) + 1;    return true;  };  bool GetEncodedFrame(void **ppBuffer, 		       uint32_t *pBufferLength) {    if (m_encodedFrame == NULL) return false;    *pBufferLength = m_encodedFrameLen;#ifdef DEBUG_TEXT    debug_message("encode len %u", *pBufferLength);#endif    *ppBuffer = strdup(m_encodedFrame);    return true;  };  char *m_encodedFrame;  uint32_t m_encodedFrameLen;  const char *m_base_url;  uint32_t m_base_url_len;};CTextEncoder* TextEncoderCreate(CTextProfile *tp, 				uint16_t mtu,				CTextEncoder *next, 				bool realTime){  const char *encoding = tp->GetStringValue(CFG_TEXT_ENCODING);  if (strcmp(encoding, TEXT_ENCODING_PLAIN) == 0) {    return new CPlainTextEncoder(tp, mtu, next, realTime);  } else if (strcmp(encoding, TEXT_ENCODING_HREF) == 0) {    return new CHrefTextEncoder(tp, mtu, next, realTime);  }  return NULL;}MediaType get_text_mp4_fileinfo (CTextProfile *pConfig,				 const char **url){  const char *encoding = pConfig->GetStringValue(CFG_TEXT_ENCODING);  *url = NULL;  if (strcmp(encoding, TEXT_ENCODING_HREF) == 0) {    *url = pConfig->GetStringValue(CFG_TEXT_HREF_BASE_URL);    return HREFTEXTFRAME;  }  return UNDEFINEDFRAME;}media_desc_t *create_text_sdp (CTextProfile *pConfig){  media_desc_t *sdpMedia;  format_list_t *sdpMediaFormat;  sdpMedia = MALLOC_STRUCTURE(media_desc_t);  memset(sdpMedia, 0, sizeof(*sdpMedia));  sdpMediaFormat = MALLOC_STRUCTURE(format_list_t);  memset(sdpMediaFormat, 0, sizeof(*sdpMediaFormat));  sdpMediaFormat->media = sdpMedia;  sdpMediaFormat->fmt = strdup("98");  sdpMediaFormat->rtpmap_clock_rate = 90000;  sdpMedia->fmt_list = sdpMediaFormat;  if (strcmp(pConfig->GetStringValue(CFG_TEXT_ENCODING), 	     TEXT_ENCODING_PLAIN) == 0) {    // text    sdpMediaFormat->rtpmap_name = strdup("x-plain-text");    sdpMedia->media = strdup("application");  } else {    sdpMediaFormat->rtpmap_name = strdup("X-HREF");    sdpMedia->media = strdup("control");    const char *base_url = pConfig->GetStringValue(CFG_TEXT_HREF_BASE_URL);    if (base_url != NULL) {      char *temp = (char *)malloc(strlen("base_url=") + strlen(base_url) + 1);      sprintf(temp,"base_url=%s", base_url);      sdpMediaFormat->fmt_param = temp;    }  }    return sdpMedia;}void create_mp4_text_hint_track (CTextProfile *pConfig, 				 MP4FileHandle mp4file,				 MP4TrackId trackId,				 uint16_t mtu){  if (strcasecmp(pConfig->GetStringValue(CFG_TEXT_ENCODING), TEXT_ENCODING_HREF) == 0) {    HrefHinter(mp4file, trackId, mtu);  }}static void SendPlainText (CMediaFrame *pFrame,			   CRtpDestination *list,			   uint32_t rtpTimestamp,			   uint16_t mtu){  CRtpDestination *rdptr;  uint32_t bytesToSend = pFrame->GetDataLength();  struct iovec iov;  uint8_t *pData = (uint8_t *)pFrame->GetData();    while (bytesToSend) {    uint32_t payloadLength;    bool lastPacket;    if (bytesToSend < mtu) {      payloadLength = bytesToSend;      lastPacket = true;    } else {      payloadLength = mtu;      lastPacket = false;    }    iov.iov_base = pData;    iov.iov_len = payloadLength;    rdptr = list;    while (rdptr != NULL) {      int rc = rdptr->send_iov(&iov, 1, rtpTimestamp, lastPacket);      if (rc != (int)payloadLength) {	error_message("text send send_iov error - returned %d %d", 		      rc, payloadLength);      }      rdptr = rdptr->get_next();    }    pData += payloadLength;    bytesToSend -= payloadLength;  }  if (pFrame->RemoveReference())     delete pFrame;}static void SendHrefText (CMediaFrame *pFrame,			  CRtpDestination *list,			  uint32_t rtpTimestamp,			  uint16_t mtu){  CRtpDestination *rdptr;  uint32_t bytesToSend = pFrame->GetDataLength();  struct iovec iov[2];  uint8_t *pData = (uint8_t *)pFrame->GetData();    if (pFrame->GetDataLength() + 4 > mtu) {    error_message("Href url is too long - not transmitting \"%s\"", 		  (char *)pData);    return;  }    uint8_t header[4];  header[0] = 0;  header[1] = 1;  header[2] = bytesToSend >> 8;  header[3] = bytesToSend & 0xff;  iov[0].iov_base = header;  iov[0].iov_len = 4;  iov[1].iov_base = pData;  iov[1].iov_len = bytesToSend;  rdptr = list;  while (rdptr != NULL) {    int rc = rdptr->send_iov(iov, 2, rtpTimestamp, true);    rc -= 4;     if (rc != (int)bytesToSend) {      error_message("text send send_iov error - returned %d %d", 		    rc, bytesToSend);    }    rdptr = rdptr->get_next();  }  if (pFrame->RemoveReference())     delete pFrame;}rtp_transmitter_f GetTextRtpTransmitRoutine (CTextProfile *pConfig, 					     MediaType *pType, 					     uint8_t *pPayload){  *pPayload = 98;  if (strcmp(pConfig->GetStringValue(CFG_TEXT_ENCODING),	     TEXT_ENCODING_PLAIN)  == 0) {    *pType = PLAINTEXTFRAME;    return SendPlainText;  } else if (strcmp(pConfig->GetStringValue(CFG_TEXT_ENCODING),		    TEXT_ENCODING_HREF) == 0) {    *pType = HREFTEXTFRAME;    return SendHrefText;  }  return NULL;}CTextEncoder::CTextEncoder (CTextProfile *tp,			    uint16_t mtu,			    CTextEncoder *next,			    bool realTime) :  CMediaCodec(tp, mtu, next, realTime){  }int CTextEncoder::ThreadMain (void){  CMsg* pMsg;  bool stop = false;    Init();  m_textDstType = GetFrameType();  double temp = Profile()->GetFloatValue(CFG_TEXT_REPEAT_TIME_SECS);  temp *= 1000.0;  uint32_t wait_time = (uint32_t)temp;  while (stop == false) {    int rc = SDL_SemWaitTimeout(m_myMsgQueueSemaphore, wait_time);    if (rc == 0) {      pMsg = m_myMsgQueue.get_message();      if (pMsg != NULL) {	switch (pMsg->get_value()) {	case MSG_NODE_STOP_THREAD:	  debug_message("text %s stop received", 			Profile()->GetName());	  DoStopText();	  stop = true;	  break;	case MSG_NODE_START:	  // DoStartTransmit();  Anything ?	  break;	case MSG_NODE_STOP:	  DoStopText();	  break;	case MSG_SINK_FRAME: {	  uint32_t dontcare;	  CMediaFrame *mf = (CMediaFrame*)pMsg->get_message(dontcare);	  if (m_stop_thread == false)	    ProcessTextFrame(mf);	  if (mf->RemoveReference()) {	    delete mf;	  }	  break;	}	}      	delete pMsg;      }     } else if (rc == SDL_MUTEX_TIMEDOUT) {      SendFrame(GetTimestamp());    }  }  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;  }  debug_message("text encoder %s exit", Profile()->GetName());  return 0;}void CTextEncoder::ProcessTextFrame (CMediaFrame *pFrame){  const char *fptr = (const char *)pFrame->GetData();  EncodeFrame(fptr);    SendFrame(pFrame->GetTimestamp());}void CTextEncoder::SendFrame (Timestamp t){  CMediaFrame *mf;  void *buf;  uint32_t buflen;  if (GetEncodedFrame(&buf, &buflen) == false) {    return;  }  //debug_message("encode %p", buf);  mf = new CMediaFrame(m_textDstType,		       buf, 		       buflen,		       t);#ifdef DEBUG_TEXT  debug_message("frame len %u", buflen);#endif  ForwardFrame(mf);}void CTextEncoder::DoStopText (void){}void CTextEncoder::AddRtpDestination (CMediaStream *stream,				       bool disable_ts_offset, 				       uint16_t max_ttl,				       in_port_t srcPort){  mp4live_rtp_params_t *mrtp;  mrtp = MALLOC_STRUCTURE(mp4live_rtp_params_t);  rtp_default_params(&mrtp->rtp_params);  mrtp->rtp_params.rtp_addr = stream->GetStringValue(STREAM_TEXT_DEST_ADDR);  mrtp->rtp_params.rtp_rx_port = srcPort;  mrtp->rtp_params.rtp_tx_port = stream->GetIntegerValue(STREAM_TEXT_DEST_PORT);  mrtp->rtp_params.rtp_ttl = max_ttl;  mrtp->rtp_params.transmit_initial_rtcp = 1;  mrtp->rtp_params.rtcp_addr = stream->GetStringValue(STREAM_TEXT_RTCP_DEST_ADDR);  mrtp->rtp_params.rtcp_tx_port = stream->GetIntegerValue(STREAM_TEXT_RTCP_DEST_PORT);  mrtp->use_srtp = stream->GetBoolValue(STREAM_TEXT_USE_SRTP);  mrtp->srtp_params.enc_algo =     (srtp_enc_algos_t)stream->GetIntegerValue(STREAM_TEXT_SRTP_ENC_ALGO);  mrtp->srtp_params.auth_algo =     (srtp_auth_algos_t)stream->GetIntegerValue(STREAM_TEXT_SRTP_AUTH_ALGO);  mrtp->srtp_params.tx_key = stream->m_text_key;  mrtp->srtp_params.tx_salt = stream->m_text_salt;  mrtp->srtp_params.rx_key = stream->m_text_key;  mrtp->srtp_params.rx_salt = stream->m_text_salt;  mrtp->srtp_params.rtp_enc = stream->GetBoolValue(STREAM_TEXT_SRTP_RTP_ENC);  mrtp->srtp_params.rtp_auth = stream->GetBoolValue(STREAM_TEXT_SRTP_RTP_AUTH);  mrtp->srtp_params.rtcp_enc = stream->GetBoolValue(STREAM_TEXT_SRTP_RTCP_ENC);  AddRtpDestInt(disable_ts_offset, mrtp);}

⌨️ 快捷键说明

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