📄 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-2005. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com * video aspect ratio by: * Peter Maersk-Moller peter @maersk-moller.net *//* * player_session.cpp - describes player session class, which is the * main access point for the player */#include "mpeg4ip.h"#include "player_session.h"#include "player_media.h"#include "player_sdp.h"#include "player_util.h"#include "audio.h"#include "video.h"#include "media_utils.h"#include "our_config_file.h"#ifdef _WIN32DEFINE_MESSAGE_MACRO(sync_message, "avsync")#else#define sync_message(loglevel, fmt...) message(loglevel, "avsync", fmt)#endifCPlayerSession::CPlayerSession (CMsgQueue *master_mq, SDL_sem *master_sem, const char *name, control_callback_vft_t *cc_vft, void *video_persistence, double start_time){ m_cc_vft = cc_vft; m_start_time_param = start_time; m_sdp_info = NULL; m_my_media = NULL; m_rtsp_client = NULL; m_timed_sync_list = NULL; m_video_list = 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 = false; m_streaming = false; 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_hardware_error = 0; m_fullscreen = false; m_pixel_height = -1; m_pixel_width = -1; m_session_control_url = NULL; 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; m_have_audio_rtcp_sync = false; m_screen_scale = 2; m_set_end_time = 0; m_dont_send_first_rtsp_play = 0; // if we are passed a persistence, it is grabbed... m_video_persistence = video_persistence; m_grabbed_video_persistence = m_video_persistence != NULL; m_init_tries_made_with_media = 0; m_init_tries_made_with_no_media = 0; m_message[0] = '\0'; m_stop_processing = SDL_CreateSemaphore(0); m_audio_count = m_video_count = m_text_count = 0; m_mouse_click_callback = NULL; m_audio_rtp_session = m_video_rtp_session = NULL;}CPlayerSession::~CPlayerSession (){ int hadthread = 0; // indicate that we want to stop the start-up processing SDL_SemPost(m_stop_processing);#ifndef NEED_SDL_VIDEO_IN_MAIN_THREAD 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_session_control_url, &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_stop_processing != NULL) { SDL_DestroySemaphore(m_stop_processing); m_stop_processing = NULL; } if (m_sync_sem) { SDL_DestroySemaphore(m_sync_sem); m_sync_sem = NULL; } int quit_sdl = 1; if (m_video_list != NULL) { // we need to know if we should quit SDL or not. If the control // code has grabbed the persistence, we don't want to quit if (m_video_list->grabbed_video_persistence() != 0) { quit_sdl = 0; } } CTimedSync *ts; while (m_timed_sync_list != NULL) { ts = m_timed_sync_list->GetNext(); delete m_timed_sync_list; m_timed_sync_list = ts; } if (m_grabbed_video_persistence) { sync_message(LOG_DEBUG, "grabbed persist"); quit_sdl = 0; } 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 && quit_sdl != 0) { SDL_Quit(); }}// start will basically start the sync thread, which will call// start_session_workbool CPlayerSession::start (bool use_thread){ m_sync_sem = SDL_CreateSemaphore(0); #ifdef NEED_SDL_VIDEO_IN_MAIN_THREAD use_thread = false;#endif if (use_thread) { m_sync_thread = SDL_CreateThread(c_sync_thread, this); } else { return start_session_work(); } return true;}// API from the sync task - this will start the session// while this is running (except if NEED_SDL_VIDEO_IN_MAIN_THREAD),// callees from parse_name_for_session can call ShouldStopProcessing// to see if they should stop what they are doing.bool CPlayerSession::start_session_work (void){ int ret; bool err = false; ret = parse_name_for_session(this, get_session_name(), m_cc_vft); if (ret >= 0) { if (play_all_media(TRUE, m_start_time_param) < 0) { err = true; } if (err == false) { m_master_msg_queue->send_message(ret > 0 ? MSG_SESSION_WARNING : MSG_SESSION_STARTED, m_master_msg_queue_sem); } m_init_time = get_time_of_day(); } else { err = true; } if (err) { m_master_msg_queue->send_message(MSG_SESSION_ERROR, m_master_msg_queue_sem); return false; } return true;}int CPlayerSession::create_streaming_broadcast (session_desc_t *sdp){ session_set_seekable(0); m_sdp_info = sdp; m_streaming = true; m_streaming_ondemand = 0; 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, 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, config.GetStringValue(CONFIG_RTSP_PROXY_ADDR), config.GetIntegerValue(CONFIG_RTSP_PROXY_PORT)); } else { m_rtsp_client = rtsp_create_client(url, &err, config.GetStringValue(CONFIG_RTSP_PROXY_ADDR), config.GetIntegerValue(CONFIG_RTSP_PROXY_PORT)); } if (m_rtsp_client == NULL) { set_message("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. */ int rtsp_resp; rtsp_resp = rtsp_send_describe(m_rtsp_client, &cmd, &decode); if (rtsp_resp != RTSP_RESPONSE_GOOD) { int retval; if (decode != NULL) { retval = (((decode->retcode[0] - '0') * 100) + ((decode->retcode[1] - '0') * 10) + (decode->retcode[2] - '0')); set_message("RTSP describe error %d %s", retval, decode->retresp != NULL ? decode->retresp : ""); free_decode_response(decode); } else { retval = -1; set_message("RTSP return invalid %d", rtsp_resp); } player_error_message("Describe response not good\n"); return (retval); } sdpdecode = set_sdp_decode_from_memory(decode->body); if (sdpdecode == NULL) { set_message("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) { set_message("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) { set_message("Incorrect number of sessions in sdp decode %d", dummy); player_error_message("%s", get_message()); free_decode_response(decode); return (-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); if (m_sdp_info->control_string != NULL) { player_debug_message("setting control url to %s", m_sdp_info->control_string); set_session_control_url(m_sdp_info->control_string); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -