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

📄 player_media.cpp

📁 jpeg and mpeg 编解码技术源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
      if (strncasecmp(transport, 
		      transport_types[ix].name, 
		      transport_types[ix].namelen - 1) == 0) {
	transport += transport_types[ix].namelen - 1;
	ADV_SPACE(transport);
	transport = (transport_types[ix].routine)(transport, this);
	break;
      }
    }
    if (transport_types[ix].name == NULL) {
      media_message(LOG_INFO, "Illegal mime type in transport - skipping %s", 
			   transport);
      while (*transport != ';' && *transport != '\0') transport++;
      if (*transport != '\0') transport++;
    }
  } while (transport != NULL && *transport != '\0');

  if (transport == NULL) {
    return (-1);
  }
  return (0);
}

struct {
  const char *name;
  uint32_t namelen;
  char *(*routine)(char *transport, CPlayerMedia *, int &end_for_url);
} rtpinfo_types[] = 
{
  TTYPE("seq", rtpinfo_parse_seq),
  TTYPE("rtptime", rtpinfo_parse_rtptime),
  TTYPE("ssrc", rtpinfo_parse_ssrc),
  {NULL, 0, NULL},
};

int process_rtsp_rtpinfo (char *rtpinfo, 
			  CPlayerSession *session,
			  CPlayerMedia *media)
{
  int ix;
  CPlayerMedia *newmedia;
  if (rtpinfo == NULL) 
    return (0);

  do {
    int no_mimes = 0;
    ADV_SPACE(rtpinfo);
    if (strncasecmp(rtpinfo, "url", strlen("url")) != 0) {
      media_message(LOG_ERR, "Url not found");
      return (-1);
    }
    rtpinfo += strlen("url");
    ADV_SPACE(rtpinfo);
    if (*rtpinfo != '=') {
      media_message(LOG_ERR, "Can't find = after url");
      return (-1);
    }
    rtpinfo++;
    ADV_SPACE(rtpinfo);
    char *url = rtpinfo;
    while (*rtpinfo != '\0' && *rtpinfo != ';' && *rtpinfo != ',') {
      rtpinfo++;
    }
    if (*rtpinfo == '\0') {
      no_mimes = 1;
    } else {
      if (*rtpinfo == ',') {
	no_mimes = 1;
      }
      *rtpinfo++ = '\0';
    }
    char *temp = url;
    newmedia = session->rtsp_url_to_media(url);
    if (newmedia == NULL) {
      media_message(LOG_ERR, "Can't find media from %s", url);
      return -1;
    } else if (media != NULL && media != newmedia) {
      media_message(LOG_ERR, "Url in rtpinfo does not match media %s", url);
      return -1;
    }
    if (temp != url) 
      free(url);

    if (no_mimes == 0) {
    int endofurl = 0;
    do {
      ADV_SPACE(rtpinfo);
      for (ix = 0; rtpinfo_types[ix].name != NULL; ix++) {
	if (strncasecmp(rtpinfo,
			rtpinfo_types[ix].name, 
			rtpinfo_types[ix].namelen - 1) == 0) {
	  rtpinfo += rtpinfo_types[ix].namelen - 1;
	  ADV_SPACE(rtpinfo);
	  rtpinfo = (rtpinfo_types[ix].routine)(rtpinfo, newmedia, endofurl);
	  break;
	}
      }
      if (rtpinfo_types[ix].name == NULL) {
#if 1
	media_message(LOG_INFO, "Unknown mime-type in RtpInfo - skipping %s", 
			     rtpinfo);
#endif
	while (*rtpinfo != ';' && *rtpinfo != '\0') rtpinfo++;
	if (*rtpinfo != '\0') rtpinfo++;
      }
    } while (endofurl == 0 && rtpinfo != NULL && *rtpinfo != '\0');
    } 
    newmedia = NULL;
  } while (rtpinfo != NULL && *rtpinfo != '\0');

  if (rtpinfo == NULL) {
    return (-1);
  }

  return (1);
}

int CPlayerMedia::rtp_receive_packet (unsigned char interleaved, 
				      struct rtp_packet *pak, 
				      int len)
{
  int ret;
  if ((interleaved & 1) == 0) {
    ret = rtp_process_recv_data(m_rtp_session, 0, pak, len);
    if (ret < 0) {
      xfree(pak);
    }
  } else {
    uint8_t *pakbuf = (uint8_t *)pak;
    pakbuf += sizeof(rtp_packet_data);
	    
    rtp_process_ctrl(m_rtp_session, pakbuf, len);
    xfree(pak);
    ret = 0;
  }
  return ret;
}

void CPlayerMedia::rtp_periodic (void)
{
  rtp_send_ctrl(m_rtp_session, 
		m_rtp_byte_stream != NULL ? 
		m_rtp_byte_stream->get_last_rtp_timestamp() : 0, 
		NULL);
  rtp_update(m_rtp_session);
  if (m_rtp_byte_stream != NULL) {
    int ret = m_rtp_byte_stream->recv_task(m_decode_thread_waiting);
    if (ret > 0) {
      if (m_rtp_buffering == 0) {
	m_rtp_buffering = 1;
	start_decoding();
      } else {
	bytestream_primed();
      }
    }
    return;
  }
  if (m_head != NULL) {
    /*
     * Make sure that the payload type is the same
     */
    if (m_head->rtp_pak_pt == m_tail->rtp_pak_pt) {
      if (m_rtp_queue_len > 10) { // 10 packets consecutive proto same
	if (determine_payload_type_from_rtp() == FALSE) {
	  clear_rtp_packets(); 
	}
      }
    } else {
      clear_rtp_packets();
    }
  }
}

void CPlayerMedia::rtp_start (void)
{
  if (m_rtp_ssrc_set == TRUE) {
    rtp_set_my_ssrc(m_rtp_session, m_rtp_ssrc);
  } else {
    // For now - we'll set up not to wait for RTCP validation 
    // before indicating if rtp library should accept.
    rtp_set_option(m_rtp_session, RTP_OPT_WEAK_VALIDATION, FALSE);
    rtp_set_option(m_rtp_session, RTP_OPT_PROMISC, TRUE);
  }
  if (m_rtp_byte_stream != NULL) {
    //m_rtp_byte_stream->reset(); - gets called when pausing
    m_rtp_byte_stream->flush_rtp_packets();
  }
  m_rtp_buffering = 0;
}

void CPlayerMedia::rtp_end(void)
{
  if (m_rtp_session != NULL) {
    rtp_send_bye(m_rtp_session);
    rtp_done(m_rtp_session);
  }
  m_rtp_session = NULL;
}

int CPlayerMedia::rtcp_send_packet (uint8_t *buffer, int buflen)
{
  if (config.get_config_value(CONFIG_SEND_RTCP_IN_RTP_OVER_RTSP) != 0) {
    return rtsp_thread_send_rtcp(m_parent->get_rtsp_client(),
				 m_rtp_media_number_in_session,
				 buffer, 
				 buflen);
  }
  return buflen;
}
/****************************************************************************
 * RTP receive routines
 ****************************************************************************/
int CPlayerMedia::recv_thread (void)
{
  struct timeval timeout;
  int retcode;
  CMsg *newmsg;
  int recv_thread_stop = 0;
  connect_desc_t *cptr;
  int receiving = 0;
  cptr = get_connect_desc_from_media(m_media_info);


  m_rtp_buffering = 0;
  if (m_stream_ondemand != 0) {
    /*
     * We need to free up the ports that we got before RTP tries to set 
     * them up, so we don't have any re-use conflicts.  There is a small
     * window here that they might get used...
     */
    delete m_ports; // free up the port numbers
    m_ports = NULL;
  }

#ifdef _WINDOWS
  WORD wVersionRequested;
  WSADATA wsaData;
  int ret;
 
  wVersionRequested = MAKEWORD( 2, 0 );
  
  ret = WSAStartup( wVersionRequested, &wsaData );
  if ( ret != 0 ) {
    abort();
  }
#endif
  double bw;

  if (find_rtcp_bandwidth_from_media(m_media_info, &bw) < 0) {
    bw = 5000.0;
  } else {
    media_message(LOG_DEBUG, "Using bw from sdp %g", bw);
  }
  m_rtp_session = rtp_init(m_source_addr == NULL ? 
			   cptr->conn_addr : m_source_addr,
			   m_our_port,
			   m_server_port,
			   cptr == NULL ? 1 : cptr->ttl, // need ttl here
			   bw, // rtcp bandwidth ?
			   c_recv_callback,
			   (uint8_t *)this);
  if (m_rtp_session != NULL) {
    rtp_set_option(m_rtp_session, RTP_OPT_WEAK_VALIDATION, FALSE);
    rtp_set_option(m_rtp_session, RTP_OPT_PROMISC, TRUE);
  }
  m_rtp_inited = 1;
  
  while (recv_thread_stop == 0) {
    /*
     * See if we need to check for a state change - this will allow
     * changes to the rtp info, if required.
     */
    while ((newmsg = m_rtp_msg_queue.get_message()) != NULL) {
      switch (newmsg->get_value()) {
      case MSG_STOP_THREAD:
	recv_thread_stop = 1;
	continue;
      case MSG_START_SESSION:
	if (m_rtp_session == NULL) {
	  continue;
	}
	rtp_start();
	receiving = 1;
	break;
      case MSG_PAUSE_SESSION:
	break;
      }
      delete newmsg;
    }
    if (receiving == 0) {
      SDL_Delay(50);
      continue;
    }
    while (receiving == 1 && recv_thread_stop == 0) {
      if ((newmsg = m_rtp_msg_queue.get_message()) != NULL) {
	//player_debug_message("recv thread message %d", newmsg->get_value());
	switch (newmsg->get_value()) {
	case MSG_STOP_THREAD:
	  recv_thread_stop = 1;
	  break;
	case MSG_START_SESSION:
	  //media_message(LOG_ERR, "Got play when playing");
	  break;
	case MSG_PAUSE_SESSION:
	  // Indicate that we need to restart the session.
	  // But keep going...
	  media_message(LOG_DEBUG, "calling rtp start from pause");
	  rtp_start();
	  break;
	}
	delete newmsg;
	newmsg = NULL;
      }
      if (recv_thread_stop == 1) {
	continue;
      }
      timeout.tv_sec = 0;
      timeout.tv_usec = 500000;
      retcode = rtp_recv(m_rtp_session, &timeout, 0);
      //      player_debug_message("rtp_recv return %d", retcode);
      // Run rtp periodic after each packet received or idle time.
      if (m_paused == 0)
	rtp_periodic();

    }
  }
  /*
   * When we're done, send a bye, close up rtp, and go home
   */
  rtp_end();
  return (0);
}

#ifdef DROP_PAKS
static int dropcount = 0;
#endif

/*
 * CPlayerMedia::recv_callback - callback from RTP with valid data
 */
void CPlayerMedia::recv_callback (struct rtp *session, rtp_event *e)
{
  if (e == NULL) return;
  /*
   * If we're paused, just dump the packet.  Multicast case
   */
  if (m_paused != 0) {
    if (e->type == RX_RTP) {
      xfree(e->data);
      return;
    }
  }
#if DROP_PAKS
    if (e->type == RX_RTP && dropcount >= 50) {
      xfree((rtp_packet *)e->data);
      dropcount = 0;
      return;
    } else { 
      dropcount++;
    }
#endif
  if (m_rtp_byte_stream != NULL) {
    m_rtp_byte_stream->recv_callback(session, e);
    return;
  }
  switch (e->type) {
  case RX_RTP:
    /* regular rtp packet - add it to the queue */
    rtp_packet *rpak;

    rpak = (rtp_packet *)e->data;
    if (rpak->rtp_data_len == 0) {
      xfree(rpak);
    } else {
      add_rtp_packet_to_queue(rpak, &m_head, &m_tail);
      m_rtp_queue_len++;
    }
    break;
  case RX_SR:
    rtcp_sr *srpak;
    srpak = (rtcp_sr *)e->data;

    m_rtcp_ntp_frac = srpak->ntp_frac;
    m_rtcp_ntp_sec = srpak->ntp_sec;
    m_rtcp_rtp_ts = srpak->rtp_ts;
    m_rtcp_received = 1;
    break;
  default:
#if 0
    media_message(LOG_DEBUG, "Thread %u - Callback from rtp with %d %p", 
		  SDL_ThreadID(),e->type, e->data);
#endif
    break;
  }
}

/*
 * determine_payload_type_from_rtp - determine with protocol we're dealing with
 * in the rtp session.  Set various calculations for the sync task, as well...
 */
int CPlayerMedia::determine_payload_type_from_rtp(void)
{
  char payload_type = (char)m_head->rtp_pak_pt, temp;
  format_list_t *fmt;
  uint64_t tickpersec;
  CRtpByteStreamBase *bs;

  fmt = m_media_info->fmt;
  while (fmt != NULL) {
    temp = atoi(fmt->fmt);
    if (temp == payload_type) {
      m_media_fmt = fmt;
      if (fmt->rtpmap != NULL) {
	tickpersec = fmt->rtpmap->clock_rate;
      } else {
	if (payload_type >= 96) {
	  media_message(LOG_ERR, "Media %s, rtp payload type of %u, no rtp map",
			m_media_info->media, payload_type);
	  return (FALSE);
	}
	tickpersec = 90000;
      }

      bs = 
	create_rtp_byte_stream_for_format(m_media_fmt,
					  payload_type,
					  m_stream_ondemand,
					  tickpersec,
					  &m_head,
					  &m_tail,
					  m_rtsp_base_seq_received, 
					  m_rtp_base_seq,
					  m_rtsp_base_ts_received,
					  m_rtp_base_ts,
					  m_rtcp_received,
					  m_rtcp_ntp_frac,
					  m_rtcp_ntp_sec,
					  m_rtcp_rtp_ts);
      bs->set_start_time((uint64_t)(m_play_start_time * 1000.0));
      m_rtp_byte_stream = bs;
      m_byte_stream = m_rtp_byte_stream;
#if 1
      media_message(LOG_DEBUG, "media %s - rtp tps %u ntp per rtp ",
			   m_media_info->media,
			   m_rtptime_tickpersec);
#endif

      return (TRUE);
    }
    fmt = fmt->next;
  }
  return (FALSE);
}

/*
 * set up rtptime
 */
void CPlayerMedia::set_rtp_base_ts (uint32_t time)
{
  m_rtsp_base_ts_received = 1;
  m_rtp_base_ts = time;
  if (m_rtp_byte_stream != NULL) {
    m_rtp_byte_stream->set_rtp_base_ts(time);
  }
}

void CPlayerMedia::set_rtp_base_seq (uint16_t seq)
{
  m_rtsp_base_seq_received = 1; 
  m_rtp_base_seq = seq;
  if (m_rtp_byte_stream != NULL) {
    m_rtp_byte_stream->set_rtp_base_seq(seq);
  }
}

void CPlayerMedia::rtp_init_tcp (void) 
{
  connect_desc_t *cptr;
  cptr = get_connect_desc_from_media(m_media_info);
  m_rtp_session = rtp_init_extern_net(m_source_addr == NULL ? 
				      cptr->conn_addr : m_source_addr,
				      m_our_port,
				      m_server_port,
				      cptr->ttl,
				      5000.0, // rtcp bandwidth ?
				      c_recv_callback,
				      c_rtcp_send_packet,
				      (uint8_t *)this);
  rtp_set_option(m_rtp_session, RTP_OPT_WEAK_VALIDATION, FALSE);
  rtp_set_option(m_rtp_session, RTP_OPT_PROMISC, TRUE);
  m_rtp_inited = 1;

}
/* end player_media.cpp */

⌨️ 快捷键说明

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