📄 player_media.cpp
字号:
}
if (m_audio_sync == NULL) return -1;
m_audio_info = audio;
m_plugin = p;
m_plugin_data = (p->ac_create)(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)
{
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) {
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");
free_decode_response(decode);
return (-1);
}
/*
* process the return information
*/
int ret = process_rtsp_rtpinfo(decode->rtp_info, m_parent, this);
if (ret < 0) {
media_message(LOG_ERR, "rtsp rtpinfo failed");
free_decode_response(decode);
return (-1);
}
free_decode_response(decode);
}
if (m_source_addr == NULL) {
// get the ip address of the server from the rtsp stack
m_source_addr = strdup(inet_ntoa(get_server_ip_address(m_rtsp_session)));
media_message(LOG_INFO, "Setting source address from rtsp - %s",
m_source_addr);
}
// ASDF - probably need to do some stuff here for no rtpinfo...
/*
* set the various play times, and send a message to the recv task
* that it needs to start
*/
m_play_start_time = start_time_offset;
if (m_rtp_byte_stream != NULL) {
m_rtp_byte_stream->set_start_time((uint64_t)(start_time_offset * 1000.0));
}
}
m_paused = 0;
if (m_rtp_use_rtsp) {
rtsp_thread_perform_callback(m_parent->get_rtsp_client(),
c_rtp_start,
this);
} else {
m_rtp_msg_queue.send_message(MSG_START_SESSION);
}
} else {
/*
* File (or other) playback.
*/
if (m_paused == 0 || start_time_offset == 0.0) {
m_byte_stream->reset();
}
m_byte_stream->set_start_time((uint64_t)(start_time_offset * 1000.0));
m_play_start_time = start_time_offset;
m_paused = 0;
start_decoding();
}
return (0);
}
/*
* CPlayerMedia::do_pause - stop what we're doing
*/
int CPlayerMedia::do_pause (void)
{
if (m_streaming != 0) {
if (m_stream_ondemand != 0) {
/*
* streaming - send RTSP pause
*/
if (m_parent->session_control_is_aggregate() == 0) {
rtsp_command_t cmd;
rtsp_decode_t *decode;
memset(&cmd, 0, sizeof(rtsp_command_t));
if (rtsp_send_pause(m_rtsp_session, &cmd, &decode) != 0) {
media_message(LOG_ERR, "RTSP play command failed");
free_decode_response(decode);
return (-1);
}
free_decode_response(decode);
}
}
m_rtp_msg_queue.send_message(MSG_PAUSE_SESSION);
if (m_rtp_byte_stream) m_rtp_byte_stream->reset();
}
/*
* Pause the various threads
*/
m_decode_msg_queue.send_message(MSG_PAUSE_SESSION,
NULL,
0,
m_decode_thread_sem);
m_paused = 1;
return (0);
}
double CPlayerMedia::get_max_playtime (void)
{
if (m_byte_stream) {
return (m_byte_stream->get_max_playtime());
}
return (0.0);
}
/***************************************************************************
* Transport and RTP-Info RTSP header line parsing.
***************************************************************************/
#define ADV_SPACE(a) {while (isspace(*(a)) && (*(a) != '\0'))(a)++;}
#define TTYPE(a,b) {a, sizeof(a), b}
static char *transport_parse_unicast (char *transport, CPlayerMedia *m)
{
ADV_SPACE(transport);
if (*transport == '\0') return (transport);
if (*transport != ';')
return (NULL);
transport++;
ADV_SPACE(transport);
return (transport);
}
static char *transport_parse_multicast (char *transport, CPlayerMedia *m)
{
media_message(LOG_ERR,"Received multicast indication during SETUP");
return (NULL);
}
static char *convert_number (char *transport, uint32_t &value)
{
value = 0;
while (isdigit(*transport)) {
value *= 10;
value += *transport - '0';
transport++;
}
return (transport);
}
static char *convert_hex (char *transport, uint32_t &value)
{
value = 0;
while (isxdigit(*transport)) {
value *= 16;
if (isdigit(*transport))
value += *transport - '0';
else
value += tolower(*transport) - 'a' + 10;
transport++;
}
return (transport);
}
static char *transport_parse_client_port (char *transport, CPlayerMedia *m)
{
uint32_t port;
uint16_t our_port, our_port_max;
if (*transport++ != '=') {
return (NULL);
}
ADV_SPACE(transport);
transport = convert_number(transport, port);
ADV_SPACE(transport);
our_port = m->get_our_port();
our_port_max = our_port + 1;
if (port != our_port) {
media_message(LOG_ERR, "Returned client port %u doesn't match sent %u",
port, our_port);
return (NULL);
}
if (*transport == ';') {
transport++;
return (transport);
}
if (*transport == '\0') {
return (transport);
}
if (*transport != '-') {
return (NULL);
}
transport++;
ADV_SPACE(transport);
transport = convert_number(transport, port);
if ((port < our_port) ||
(port > our_port_max)) {
media_message(LOG_ERR, "Illegal client to port %u, range %u to %u",
port, our_port, our_port_max);
return (NULL);
}
ADV_SPACE(transport);
if (*transport == ';') {
transport++;
}
return(transport);
}
static char *transport_parse_server_port (char *transport, CPlayerMedia *m)
{
uint32_t fromport, toport;
if (*transport++ != '=') {
return (NULL);
}
ADV_SPACE(transport);
transport = convert_number(transport, fromport);
ADV_SPACE(transport);
m->set_server_port((uint16_t)fromport);
if (*transport == ';') {
transport++;
return (transport);
}
if (*transport == '\0') {
return (transport);
}
if (*transport != '-') {
return (NULL);
}
transport++;
ADV_SPACE(transport);
transport = convert_number(transport, toport);
if (toport < fromport || toport > fromport + 1) {
media_message(LOG_ERR, "Illegal server to port %u, from is %u",
toport, fromport);
return (NULL);
}
ADV_SPACE(transport);
if (*transport == ';') {
transport++;
}
return(transport);
}
static char *transport_parse_source (char *transport, CPlayerMedia *m)
{
char *ptr, *newone;
uint32_t addrlen;
if (*transport != '=') {
return (NULL);
}
transport++;
ADV_SPACE(transport);
ptr = transport;
while (*transport != ';' && *transport != '\0') transport++;
addrlen = transport - ptr;
if (addrlen == 0) {
return (NULL);
}
newone = (char *)malloc(addrlen + 1);
if (newone == NULL) {
media_message(LOG_ERR, "Can't alloc memory for transport source");
return (NULL);
}
strncpy(newone, ptr, addrlen);
newone[addrlen] = '\0';
m->set_source_addr(newone);
if (*transport == ';') transport++;
return (transport);
}
static char *transport_parse_ssrc (char *transport, CPlayerMedia *m)
{
uint32_t ssrc;
if (*transport != '=') {
return (NULL);
}
transport++;
ADV_SPACE(transport);
transport = convert_hex(transport, ssrc);
ADV_SPACE(transport);
if (*transport != '\0') {
if (*transport != ';') {
return (NULL);
}
transport++;
}
m->set_rtp_ssrc(ssrc);
return (transport);
}
static char *transport_parse_interleave (char *transport, CPlayerMedia *m)
{
uint32_t chan, chan2;
if (*transport != '=') {
return (NULL);
}
transport++;
ADV_SPACE(transport);
transport = convert_number(transport, chan);
chan2 = m->get_rtp_media_number() * 2;
if (chan != chan2) {
media_message(LOG_ERR, "Transport interleave not what was requested %d %d",
chan, chan2);
return NULL;
}
ADV_SPACE(transport);
if (*transport != '\0') {
if (*transport != '-') {
return (NULL);
}
transport++;
transport = convert_number(transport, chan2);
if (chan + 1 != chan2) {
media_message(LOG_ERR, "Error in transport interleaved field");
return (NULL);
}
if (*transport == '\0') return (transport);
}
if (*transport != ';') return (NULL);
transport++;
return (transport);
}
static char *rtpinfo_parse_ssrc (char *transport, CPlayerMedia *m, int &end)
{
uint32_t ssrc;
if (*transport != '=') {
return (NULL);
}
transport++;
ADV_SPACE(transport);
transport = convert_hex(transport, ssrc);
ADV_SPACE(transport);
if (*transport != '\0') {
if (*transport == ',') {
end = 1;
} else if (*transport != ';') {
return (NULL);
}
transport++;
}
m->set_rtp_ssrc(ssrc);
return (transport);
}
static char *rtpinfo_parse_seq (char *rtpinfo, CPlayerMedia *m, int &endofurl)
{
uint32_t seq;
if (*rtpinfo != '=') {
return (NULL);
}
rtpinfo++;
ADV_SPACE(rtpinfo);
rtpinfo = convert_number(rtpinfo, seq);
ADV_SPACE(rtpinfo);
if (*rtpinfo != '\0') {
if (*rtpinfo == ',') {
endofurl = 1;
} else if (*rtpinfo != ';') {
return (NULL);
}
rtpinfo++;
}
m->set_rtp_base_seq(seq);
return (rtpinfo);
}
static char *rtpinfo_parse_rtptime (char *rtpinfo,
CPlayerMedia *m,
int &endofurl)
{
uint32_t rtptime;
int neg = 0;
if (*rtpinfo != '=') {
return (NULL);
}
rtpinfo++;
ADV_SPACE(rtpinfo);
if (*rtpinfo == '-') {
neg = 1;
rtpinfo++;
ADV_SPACE(rtpinfo);
}
rtpinfo = convert_number(rtpinfo, rtptime);
ADV_SPACE(rtpinfo);
if (*rtpinfo != '\0') {
if (*rtpinfo == ',') {
endofurl = 1;
} else if (*rtpinfo != ';') {
return (NULL);
}
rtpinfo++;
}
if (neg != 0) {
player_error_message("Warning - negative time returned in rtpinfo");
rtptime = 0 - rtptime;
}
m->set_rtp_base_ts(rtptime);
return (rtpinfo);
}
struct {
const char *name;
uint32_t namelen;
char *(*routine)(char *transport, CPlayerMedia *);
} transport_types[] =
{
TTYPE("unicast", transport_parse_unicast),
TTYPE("multicast", transport_parse_multicast),
TTYPE("client_port", transport_parse_client_port),
TTYPE("server_port", transport_parse_server_port),
TTYPE("source", transport_parse_source),
TTYPE("ssrc", transport_parse_ssrc),
TTYPE("interleaved", transport_parse_interleave),
{NULL, 0, NULL},
};
int CPlayerMedia::process_rtsp_transport (char *transport)
{
uint32_t protolen;
int ix;
if (transport == NULL)
return (-1);
protolen = strlen(m_media_info->proto);
if (strncasecmp(transport, m_media_info->proto, protolen) != 0) {
media_message(LOG_ERR, "transport %s doesn't match %s", transport,
m_media_info->proto);
return (-1);
}
transport += protolen;
if (*transport == '/') {
transport++;
if (m_rtp_use_rtsp) {
if (strncasecmp(transport, "TCP", strlen("TCP")) != 0) {
media_message(LOG_ERR, "Transport is not TCP");
return (-1);
}
transport += strlen("TCP");
} else {
if (strncasecmp(transport, "UDP", strlen("UDP")) != 0) {
media_message(LOG_ERR, "Transport is not UDP");
return (-1);
}
transport += strlen("UDP");
}
}
if (*transport != ';') {
return (-1);
}
transport++;
do {
ADV_SPACE(transport);
for (ix = 0; transport_types[ix].name != NULL; ix++) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -