📄 player_session.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. 2000, 2001. All Rights Reserved.
*
* Contributor(s):
* Bill May wmay@cisco.com
*/
/*
* player_session.cpp - describes player session class, which is the
* main access point for the player
*/
#include "systems.h"
#include "player_session.h"
#include "player_media.h"
#include "player_sdp.h"
#include "player_util.h"
#include "audio.h"
#include "video.h"
#ifdef _WIN32
DEFINE_MESSAGE_MACRO(sync_message, "avsync")
#else
#define sync_message(loglevel, fmt...) message(loglevel, "avsync", fmt)
#endif
/*
* c callback for sync thread
*/
CPlayerSession::CPlayerSession (CMsgQueue *master_mq,
SDL_sem *master_sem,
const char *name)
{
m_sdp_info = NULL;
m_my_media = NULL;
m_rtsp_client = NULL;
m_video_sync = NULL;
m_audio_sync = NULL;
m_sync_thread = NULL;
m_sync_sem = NULL;
m_content_base = NULL;
m_master_msg_queue = master_mq;
m_master_msg_queue_sem = master_sem;
m_paused = 0;
m_streaming = 0;
m_session_name = strdup(name);
m_audio_volume = 75;
m_current_time = 0;
m_seekable = 0;
m_session_state = SESSION_PAUSED;
m_screen_pos_x = 0;
m_screen_pos_y = 0;
m_clock_wrapped = -1;
m_hardware_error = 0;
m_fullscreen = 0;
m_session_control_is_aggregate = 0;
for (int ix = 0; ix < SESSION_DESC_COUNT; ix++) {
m_session_desc[ix] = NULL;
}
m_media_close_callback = NULL;
m_media_close_callback_data = NULL;
m_streaming_media_set_up = 0;
m_unused_ports = NULL;
m_first_time_played = 0;
m_latency = 0;
}
CPlayerSession::~CPlayerSession ()
{
int hadthread = 0;
#ifndef _WINDOWS
if (m_sync_thread) {
send_sync_thread_a_message(MSG_STOP_THREAD);
SDL_WaitThread(m_sync_thread, NULL);
m_sync_thread = NULL;
hadthread = 1;
}
#else
send_sync_thread_a_message(MSG_STOP_THREAD);
hadthread = 1;
#endif
if (m_streaming_media_set_up != 0 &&
session_control_is_aggregate()) {
rtsp_command_t cmd;
rtsp_decode_t *decode;
memset(&cmd, 0, sizeof(rtsp_command_t));
rtsp_send_aggregate_teardown(m_rtsp_client,
m_sdp_info->control_string,
&cmd,
&decode);
free_decode_response(decode);
}
if (m_rtsp_client) {
free_rtsp_client(m_rtsp_client);
m_rtsp_client = NULL;
}
while (m_my_media != NULL) {
CPlayerMedia *p;
p = m_my_media;
m_my_media = p->get_next();
delete p;
}
if (m_sdp_info) {
sdp_free_session_desc(m_sdp_info);
m_sdp_info = NULL;
}
if (m_sync_sem) {
SDL_DestroySemaphore(m_sync_sem);
m_sync_sem = NULL;
}
if (m_video_sync != NULL) {
delete m_video_sync;
m_video_sync = NULL;
}
if (m_audio_sync != NULL) {
delete m_audio_sync;
m_audio_sync = NULL;
}
if (m_session_name) {
free((void *)m_session_name);
m_session_name = NULL;
}
if (m_content_base) {
free((void *) m_content_base);
m_content_base = NULL;
}
for (int ix = 0; ix < SESSION_DESC_COUNT; ix++) {
if (m_session_desc[ix] != NULL)
free((void *)m_session_desc[ix]);
m_session_desc[ix] = NULL;
}
if (m_media_close_callback != NULL) {
m_media_close_callback(m_media_close_callback_data);
}
while (m_unused_ports != NULL) {
CIpPort *first;
first = m_unused_ports;
m_unused_ports = first->get_next();
delete first;
}
if (hadthread != 0) {
SDL_Quit();
}
}
int CPlayerSession::create_streaming_broadcast (session_desc_t *sdp,
char *ermsg,
uint32_t errlen)
{
session_set_seekable(0);
m_sdp_info = sdp;
m_streaming = 1;
m_rtp_over_rtsp = 0;
return (0);
}
/*
* create_streaming - create a session for streaming. Create an
* RTSP session with the server, get the SDP information from it.
*/
int CPlayerSession::create_streaming_ondemand (const char *url,
char *errmsg,
uint32_t errlen,
int use_tcp)
{
rtsp_command_t cmd;
rtsp_decode_t *decode;
sdp_decode_info_t *sdpdecode;
int dummy;
int err;
// streaming has seek capability (at least on demand)
session_set_seekable(1);
player_debug_message("Creating streaming %s", url);
memset(&cmd, 0, sizeof(rtsp_command_t));
/*
* create RTSP session
*/
if (use_tcp != 0) {
m_rtsp_client = rtsp_create_client_for_rtp_tcp(url, &err);
} else {
m_rtsp_client = rtsp_create_client(url, &err);
}
if (m_rtsp_client == NULL) {
snprintf(errmsg, errlen, "Failed to create RTSP client");
player_error_message("Failed to create rtsp client - error %d", err);
return (err);
}
m_rtp_over_rtsp = use_tcp;
cmd.accept = "application/sdp";
/*
* Send the RTSP describe. This should return SDP information about
* the session.
*/
if (rtsp_send_describe(m_rtsp_client, &cmd, &decode) !=
RTSP_RESPONSE_GOOD) {
int retval;
if (decode != NULL) {
retval = (((decode->retcode[0] - '0') * 100) +
((decode->retcode[1] - '0') * 10) +
(decode->retcode[2] - '0'));
} else {
retval = -1;
}
snprintf(errmsg, errlen, "RTSP describe error %d %s", retval,
decode->retresp != NULL ? decode->retresp : "");
player_error_message("Describe response not good\n");
free_decode_response(decode);
return (retval);
}
sdpdecode = set_sdp_decode_from_memory(decode->body);
if (sdpdecode == NULL) {
snprintf(errmsg, errlen, "Memory failure");
player_error_message("Couldn't get sdp decode\n");
free_decode_response(decode);
return (-1);
}
/*
* Decode the SDP information into structures we can use.
*/
err = sdp_decode(sdpdecode, &m_sdp_info, &dummy);
free(sdpdecode);
if (err != 0) {
snprintf(errmsg, errlen, "Couldn't decode session description %s",
decode->body);
player_error_message("Couldn't decode sdp %s", decode->body);
free_decode_response(decode);
return (-1);
}
if (dummy != 1) {
snprintf(errmsg, errlen, "Incorrect number of sessions in sdp decode %d",
dummy);
player_error_message(errmsg);
free_decode_response(decode);
return (-1);
}
if (m_sdp_info->control_string != NULL) {
set_session_control(1);
}
/*
* Make sure we can use the urls in the sdp info
*/
if (decode->content_location != NULL) {
// Note - we may have problems if the content location is not absolute.
m_content_base = strdup(decode->content_location);
} else if (decode->content_base != NULL) {
m_content_base = strdup(decode->content_base);
} else {
int urllen = strlen(url);
if (url[urllen] != '/') {
char *temp;
temp = (char *)malloc(urllen + 2);
strcpy(temp, url);
strcat(temp, "/");
m_content_base = temp;
} else {
m_content_base = strdup(url);
}
}
convert_relative_urls_to_absolute(m_sdp_info,
m_content_base);
free_decode_response(decode);
m_streaming = 1;
return (0);
}
CVideoSync * CPlayerSession::set_up_video_sync (void)
{
if (m_video_sync == NULL) {
m_video_sync = create_video_sync(this);
}
return m_video_sync;
}
CAudioSync *CPlayerSession::set_up_audio_sync (void)
{
if (m_audio_sync == NULL) {
m_audio_sync = create_audio_sync(this, m_audio_volume);
}
return m_audio_sync;
}
/*
* set_up_sync_thread. Creates the sync thread, and a sync class
* for each media
*/
void CPlayerSession::set_up_sync_thread(void)
{
CPlayerMedia *media;
media = m_my_media;
while (media != NULL) {
if (media->is_video()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -