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

📄 player_media.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):  *              Bill May        wmay@cisco.com *//* * player_media.cpp - handle generic information about a stream */#include "systems.h"#include "player_session.h"#include "player_media.h"#include "player_sdp.h"#include "player_util.h"#include <rtp/memory.h>#include "rtp_bytestream.h"#include "our_config_file.h"#include "media_utils.h"#include "ip_port.h"#include "codec_plugin.h"#include "audio.h"//#define DROP_PAKS 1/* * c routines for callbacks */static int c_recv_thread (void *data){  CPlayerMedia *media;  media = (CPlayerMedia *)data;  return (media->recv_thread());}static int c_decode_thread (void *data){  CPlayerMedia *media;  media = (CPlayerMedia *)data;  return (media->decode_thread());}static void c_rtp_packet_callback (void *data, 				   unsigned char interleaved, 				   struct rtp_packet *pak, 				   int len){  ((CPlayerMedia *)data)->rtp_receive_packet(interleaved, pak, len);}static int c_init_rtp_tcp (void *data){  ((CPlayerMedia *)data)->rtp_init_tcp();  return 0;}static int c_rtp_start (void *data){  ((CPlayerMedia *)data)->rtp_start();  return 0;}static int c_rtp_periodic (void *data){  ((CPlayerMedia *)data)->rtp_periodic();  return 0;}CPlayerMedia::CPlayerMedia (CPlayerSession *p){  m_plugin = NULL;  m_plugin_data = NULL;  m_next = NULL;  m_parent = p;  m_media_info = NULL;  m_media_fmt = NULL;  m_our_port = 0;  m_ports = NULL;  m_server_port = 0;  m_source_addr = NULL;  m_recv_thread = NULL;  m_rtptime_tickpersec = 0;  m_rtsp_base_seq_received = 0;  m_rtsp_base_ts_received = 0;  m_head = NULL;  m_rtp_queue_len = 0;  m_rtp_ssrc_set = FALSE;    m_rtsp_session = NULL;  m_decode_thread_waiting = 0;  m_sync_time_set = FALSE;  m_decode_thread = NULL;  m_decode_thread_sem = NULL;  m_video_sync = NULL;  m_audio_sync = NULL;  m_paused = 0;  m_byte_stream = NULL;  m_rtp_byte_stream = NULL;  m_video_info = NULL;  m_audio_info = NULL;  m_user_data = NULL;  m_rtcp_received = 0;  m_streaming = 0;  m_stream_ondemand = 0;  m_rtp_use_rtsp = 0;}CPlayerMedia::~CPlayerMedia(){  rtsp_decode_t *rtsp_decode;  media_message(LOG_DEBUG, "closing down media %d", m_is_video);  if (m_rtsp_session) {    // If control is aggregate, m_rtsp_session will be freed by    // CPlayerSession    if (m_parent->session_control_is_aggregate() == 0) {      rtsp_send_teardown(m_rtsp_session, NULL, &rtsp_decode);      free_decode_response(rtsp_decode);    }    m_rtsp_session = NULL;  }    if (m_recv_thread) {    m_rtp_msg_queue.send_message(MSG_STOP_THREAD);    SDL_WaitThread(m_recv_thread, NULL);    m_recv_thread = NULL;  }  if (m_decode_thread) {    m_decode_msg_queue.send_message(MSG_STOP_THREAD, 				    NULL, 				    0, 				    m_decode_thread_sem);    SDL_WaitThread(m_decode_thread, NULL);    m_decode_thread = NULL;  }      if (m_source_addr != NULL) free(m_source_addr);  m_next = NULL;  m_parent = NULL;  if (m_ports) {    delete m_ports;    m_ports = NULL;  }  if (m_rtp_byte_stream) {    double diff;    diff = difftime(time(NULL), m_start_time);    media_message(LOG_INFO, "Media %s", m_media_info->media);        media_message(LOG_INFO, "Time: %g seconds", diff);#if 0    double div;    player_debug_message("Packets received: %u", m_rtp_packet_received);    player_debug_message("Payload received: "LLU" bytes", m_rtp_data_received);    div = m_rtp_packet_received / diff;    player_debug_message("Packets per sec : %g", div);    div = UINT64_TO_DOUBLE(m_rtp_data_received);	div *= 8.0;	div /= diff;    media_message(LOG_INFO, "Bits per sec   : %g", div);#endif			   }  if (m_byte_stream) {    delete m_byte_stream;    m_byte_stream = NULL;    m_rtp_byte_stream = NULL;  }  if (m_video_info) {    free(m_video_info);    m_video_info = NULL;  }  if (m_audio_info) {    free(m_audio_info);    m_audio_info = NULL;  }  if (m_user_data) {    free((void *)m_user_data);    m_user_data = NULL;  }  if (m_decode_thread_sem) {    SDL_DestroySemaphore(m_decode_thread_sem);    m_decode_thread_sem = NULL;  }}void CPlayerMedia::clear_rtp_packets (void){  if (m_head != NULL) {    m_tail->rtp_next = NULL;    while (m_head != NULL) {      rtp_packet *p;      p = m_head;      m_head = m_head->rtp_next;      p->rtp_next = p->rtp_prev = NULL;      xfree(p);    }  }  m_tail = NULL;  m_rtp_queue_len = 0;}int CPlayerMedia::create_common (int is_video, char *errmsg, uint32_t errlen){  m_parent->add_media(this);  m_is_video = is_video;  m_decode_thread_sem = SDL_CreateSemaphore(0);  m_decode_thread = SDL_CreateThread(c_decode_thread, this);  if (m_decode_thread_sem == NULL || m_decode_thread == NULL) {    const char *outmedia;    if (m_media_info == NULL) {      outmedia = m_is_video ? "video" : "audio";    } else outmedia = m_media_info->media;    if (errmsg != NULL)      snprintf(errmsg, errlen, "Couldn't start media thread for %s", 	       outmedia);    media_message(LOG_ERR, "Failed to create decode thread for media %s",		  outmedia);    return (-1);  }  return 0;}/* * CPlayerMedia::create - create when we've already got a * bytestream */int CPlayerMedia::create (COurInByteStream *b, 			  int is_video,			  char *errmsg,			  uint32_t errlen,			  int streaming){  m_byte_stream = b;  m_streaming = streaming;  return create_common(is_video, errmsg, errlen);}/* * CPlayerMedia::create_streaming - create a streaming media session, * including setting up rtsp session, rtp and rtp bytestream */int CPlayerMedia::create_streaming (media_desc_t *sdp_media,				    char *errmsg,				    uint32_t errlen,				    int ondemand,				    int use_rtsp,				    int media_number_in_session){  char buffer[80];  rtsp_command_t cmd;  rtsp_decode_t *decode;    m_streaming = 1;  if (sdp_media == NULL) {    snprintf(errmsg, errlen, "Internal media error - sdp is NULL");    return(-1);  }  if (strncasecmp(sdp_media->proto, "RTP", strlen("RTP")) != 0) {    snprintf(errmsg, errlen, "Media %s doesn't use RTP", sdp_media->media);    media_message(LOG_ERR, "%s doesn't use RTP", sdp_media->media);    return (-1);  }  if (sdp_media->fmt == NULL) {    snprintf(errmsg, errlen, "Media %s doesn't have any usuable formats",	     sdp_media->media);    media_message(LOG_ERR, "%s doesn't have any formats", 		  sdp_media->media);    return (-1);  }  m_media_info = sdp_media;  m_stream_ondemand = ondemand;  if (ondemand != 0) {    /*     * Get 2 consecutive IP ports.  If we don't have this, don't even     * bother     */    if (use_rtsp == 0) {      m_ports = new C2ConsecIpPort(m_parent->get_unused_ip_port_ptr());      if (m_ports == NULL || !m_ports->valid()) {	snprintf(errmsg, errlen, "Could not find any valid IP ports");	media_message(LOG_ERR, "Couldn't get valid IP ports");	return (-1);      }      m_our_port = m_ports->first_port();      /*       * Send RTSP setup message - first create the transport string for that       * message       */      create_rtsp_transport_from_sdp(m_parent->get_sdp_info(),				     m_media_info,				     m_our_port,				     buffer,				     sizeof(buffer));    } else {      m_rtp_use_rtsp = 1;      m_rtp_media_number_in_session = media_number_in_session;      snprintf(buffer, sizeof(buffer), "RTP/AVP/TCP;unicast;interleaved=%d-%d",	       media_number_in_session * 2, (media_number_in_session * 2) + 1);    }    memset(&cmd, 0, sizeof(rtsp_command_t));    cmd.transport = buffer;    int err =       rtsp_send_setup(m_parent->get_rtsp_client(),		      m_media_info->control_string,		      &cmd,		      &m_rtsp_session,		      &decode,		      m_parent->session_control_is_aggregate());    if (err != 0) {      snprintf(errmsg, errlen, "Couldn't set up session %s", 	       m_media_info->control_string);      media_message(LOG_ERR, "Can't create session %s - error code %d", 		    m_media_info->media, err);      if (decode != NULL)	free_decode_response(decode);      return (-1);    }    cmd.transport = NULL;    media_message(LOG_INFO, "Transport returned is %s", decode->transport);    /*     * process the transport they sent.  They need to send port numbers,      * addresses, rtptime information, that sort of thing     */    if (process_rtsp_transport(decode->transport) != 0) {      snprintf(errmsg, errlen, "Couldn't process transport information in RTSP response: %s", decode->transport);      free_decode_response(decode);      return(-1);    }    free_decode_response(decode);  } else {    m_server_port = m_our_port = m_media_info->port;  }  connect_desc_t *cptr;  cptr = get_connect_desc_from_media(m_media_info);  if (cptr == NULL) {    snprintf(errmsg, errlen, "Server did not return address");    return (-1);  }  //  // okay - here we want to check that the server port is set up, and  // go ahead and init rtp, and the associated task  //  m_start_time = time(NULL);  if (create_common(strcmp(sdp_media->media, "video") == 0, 		    errmsg, errlen) < 0) {    return -1;  }  if (ondemand == 0 || use_rtsp == 0) {    m_rtp_inited = 0;    m_recv_thread = SDL_CreateThread(c_recv_thread, this);    if (m_recv_thread == NULL) {      snprintf(errmsg, errlen, "Couldn't create media %s RTP recv thread",	       m_media_info->media);      media_message(LOG_ERR, errmsg);      return (-1);    }    while (m_rtp_inited == 0) {      SDL_Delay(10);    }    if (m_rtp_session == NULL) {      snprintf(errmsg, errlen, "Could not start RTP - check debug log");      media_message(LOG_ERR, errmsg);      return (-1);    }  } else {    int ret;    ret = rtsp_thread_set_rtp_callback(m_parent->get_rtsp_client(),				       c_rtp_packet_callback,				       c_rtp_periodic,				       m_rtp_media_number_in_session,				       this);    if (ret < 0) {      snprintf(errmsg, errlen, "Can't setup TCP/RTP callback");      return -1;    }    ret = rtsp_thread_perform_callback(m_parent->get_rtsp_client(),				       c_init_rtp_tcp,				       this);    if (ret < 0) {      snprintf(errmsg, errlen,  "Can't init RTP in RTSP thread");      return -1;    }  }  if (m_rtp_session == NULL) {    snprintf(errmsg, errlen, "Couldn't create RTP session for media %s",	     m_media_info->media);    media_message(LOG_ERR, errmsg);    return (-1);  }  return (0);}int CPlayerMedia::create_video_plugin (const codec_plugin_t *p,				       const char *compressor, 				       int type, 				       int profile, 				       format_list_t *sdp_media,				       video_info_t *video,				       const uint8_t *user_data,				       uint32_t userdata_size){  if (m_video_sync == NULL) {    m_video_sync = m_parent->set_up_video_sync();  }  if (m_video_sync == NULL) return -1;  m_plugin = p;  m_video_info = video;  m_plugin_data = (p->vc_create)(compressor, 				 type,				 profile, sdp_media,				 video,				 user_data,				 userdata_size,				 get_video_vft(),				 m_video_sync);  if (m_plugin_data == NULL)     return -1;  if (user_data != NULL)     set_user_data(user_data, userdata_size);  return 0;}void CPlayerMedia::set_plugin_data (const codec_plugin_t *p, 				    codec_data_t *d, 				    video_vft_t *v, 				    audio_vft_t *a){  m_plugin = p;  m_plugin_data = d;  if (is_video()) {    if (m_video_sync == NULL) {      m_video_sync = m_parent->set_up_video_sync();    }    d->ifptr = m_video_sync;    d->v.video_vft = v;  } else {    if (m_audio_sync == NULL) {      m_audio_sync = m_parent->set_up_audio_sync();    }    d->ifptr = m_audio_sync;    d->v.audio_vft = a;  }    }int CPlayerMedia::get_plugin_status (char *buffer, uint32_t buflen){  if (m_plugin == NULL) return -1;  if (m_plugin->c_print_status == NULL) return -1;  return ((m_plugin->c_print_status)(m_plugin_data, buffer, buflen));}int CPlayerMedia::create_audio_plugin (const codec_plugin_t *p,				       const char *compressor, 				       int type, 				       int profile,				       format_list_t *sdp_media,				       audio_info_t *audio,				       const uint8_t *user_data,				       uint32_t userdata_size){  if (m_audio_sync == NULL) {    m_audio_sync = m_parent->set_up_audio_sync();  }  if (m_audio_sync == NULL) return -1;  m_audio_info = audio;  m_plugin = p;  m_plugin_data = (p->ac_create)(compressor,				 type, 				 profile, 				 sdp_media,				 audio,				 user_data,				 userdata_size,				 get_audio_vft(),				 m_audio_sync);  if (m_plugin_data == NULL) return -1;  if (user_data != NULL)    set_user_data(user_data, userdata_size);  return 0;}/* * CPlayerMedia::do_play - get play command */int CPlayerMedia::do_play (double start_time_offset,			   char *errmsg, 			   uint32_t errlen){  if (m_streaming != 0) {    if (m_stream_ondemand != 0) {      /*       * We're streaming - send the RTSP play command       */      if (m_parent->session_control_is_aggregate() == 0) {	char buffer[80];	rtsp_command_t cmd;	rtsp_decode_t *decode;	range_desc_t *range;	memset(&cmd, 0, sizeof(rtsp_command_t));	// only do range if we're not paused	range = get_range_from_media(m_media_info);	if (range == NULL) {	  if (errmsg != NULL) {	    snprintf(errmsg, errlen, "Can't find range in media play");	  }	  return (-1);	}	if (start_time_offset < range->range_start || 	    start_time_offset > range->range_end) 	  start_time_offset = range->range_start;	// need to check for smpte	sprintf(buffer, "npt=%g-%g", start_time_offset, range->range_end);	cmd.range = buffer;	if (rtsp_send_play(m_rtsp_session, &cmd, &decode) != 0) {	  media_message(LOG_ERR, "RTSP play command failed");	  if (errmsg != NULL) {	    snprintf(errmsg, errlen, "RTSP Play Error %s-%s", 		     decode->retcode,		     decode->retresp != NULL ? decode->retresp : "");	  }	  free_decode_response(decode);	  return (-1);	}	/*	 * process the return information

⌨️ 快捷键说明

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