📄 rtsp_thread.c
字号:
/* * 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 *//* * rtsp_thread.c */#include "rtsp_private.h"#include <rtp/rtp.h>#include <rtp/memory.h>typedef enum rtsp_rtp_state_t { RTP_DATA_UNKNOWN = 0, RTP_DATA_START = 1, RTP_DATA_CONTINUE = 2, RTSP_HEADER_CHECK = 3, RTP_HEADER_CHECK = 4,} rtsp_rtp_state_t;#ifdef DEBUG_RTP_STATESstatic const char *states[] = { "DATA UNKNOWN", "DATA START", "DATA CONTINUE", "RTSP HEADER CHECK", "RTP HEADER CHECK"};#endiftypedef struct rtp_state_t { rtp_packet *rtp_ptr; rtsp_rtp_state_t state; int try_periodic; int receiving_rtsp_response; unsigned short rtp_len, rtp_len_gotten; unsigned char header[3];} rtp_state_t;/* * rtsp_thread_start_cmd() * Handle the start command - create the socket */static int rtsp_thread_start_cmd (rtsp_client_t *info){ int ret;#ifdef _WIN32 WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD( 2, 0 ); ret = WSAStartup( wVersionRequested, &wsaData ); if ( ret != 0 ) { /* Tell the user that we couldn't find a usable */ /* WinSock DLL.*/ return (ret); }#endif ret = rtsp_create_socket(info); return (ret);}/* * rtsp_thread_send_and_get() * send a command and get the response */static int rtsp_thread_send_and_get (rtsp_client_t *info){ rtsp_msg_send_and_get_t msg; int ret; ret = rtsp_thread_ipc_receive(info, (char *)&msg, sizeof(msg)); if (ret != sizeof(msg)) { rtsp_debug(LOG_DEBUG, "Send and get - recv %d", ret); return -1; } ret = rtsp_send(info, msg.buffer, msg.buflen); rtsp_debug(LOG_DEBUG, "Send and get - send %d", ret); return ret;}static int rtsp_msg_thread_perform_callback (rtsp_client_t *info){ rtsp_msg_callback_t callback; int ret; uint32_t cbs; cbs = sizeof(callback); ret = rtsp_thread_ipc_receive(info, (char *)&callback, cbs); if (ret != cbs) { rtsp_debug(LOG_ERR, "Perform callback msg - recvd %d instead of %u", ret, cbs); return -1; } return ((callback.func)(callback.ud));}static int rtsp_msg_thread_set_rtp_callback (rtsp_client_t *info){ rtsp_msg_rtp_callback_t callback; int interleave_num; int ret; uint32_t cbs = sizeof(callback); rtsp_debug(LOG_DEBUG, "In rtsp_msg_thread_set_rtp_callback"); ret = rtsp_thread_ipc_receive(info, (char *)&callback, cbs); if (ret != cbs) { rtsp_debug(LOG_ERR, "Perform callback msg - recvd %d instead of %u", ret, cbs); return -1; } interleave_num = callback.interleave; if (interleave_num >= MAX_RTP_THREAD_SESSIONS) { return -1; } if (info->m_callback[interleave_num].rtp_callback_set != 0) { return -2; } info->m_callback[interleave_num].rtp_callback_set = 1; info->m_callback[interleave_num].rtp_callback = callback.callback_func; info->m_callback[interleave_num].rtp_periodic = callback.periodic_func; info->m_callback[interleave_num].rtp_userdata = callback.ud; return 0;}int rtsp_thread_send_rtcp (rtsp_client_t *info, int interleave, uint8_t *buffer, int buflen){ int ret; uint8_t buff[4]; buff[0] = '$'; buff[1] = (interleave * 2) + 1; buff[2] = (buflen >> 8) & 0xff; buff[3] = (buflen & 0xff); ret = send(info->server_socket, buff, 4, 0); ret += send(info->server_socket, buffer, buflen, 0); return ret;}static void callback_for_rtp_packet (rtsp_client_t *info, unsigned char interleave, rtp_packet *rtp_ptr, unsigned short rtp_len){ unsigned char which = interleave; interleave /= 2; if (info->m_callback[interleave].rtp_callback_set) { (info->m_callback[interleave].rtp_callback)(info->m_callback[interleave].rtp_userdata, which, rtp_ptr, rtp_len); } else { xfree(rtp_ptr); }}/**************************************************************************** * * Thread RTP data receive state machine * ****************************************************************************/static __inline void change_state (rtp_state_t *state, rtsp_rtp_state_t s){ if (state->state != s) { state->state = s; //rtsp_debug(LOG_DEBUG, "changing state to %d %s", s,states[s]); }}static void move_end_of_buffer (rtsp_client_t *info, int bytes){ memmove(info->m_resp_buffer, &info->m_resp_buffer[info->m_offset_on], bytes); info->m_offset_on = 0; info->m_buffer_len = bytes;}static int get_rtp_packet (rtsp_client_t *info, rtp_state_t *state){ int ret; if (state->rtp_ptr == NULL) { //rtsp_debug(LOG_DEBUG, "PAK %d %d", state->header[0], state->rtp_len); state->rtp_ptr = (rtp_packet *)xmalloc(state->rtp_len + RTP_PACKET_HEADER_SIZE); state->rtp_len_gotten = 0; } ret = rtsp_recv(info, ((char *)state->rtp_ptr) + RTP_PACKET_HEADER_SIZE + state->rtp_len_gotten, state->rtp_len - state->rtp_len_gotten); //rtsp_debug(LOG_DEBUG, "recv %d", ret); state->rtp_len_gotten += ret; if (state->rtp_len_gotten == state->rtp_len) { callback_for_rtp_packet(info, state->header[0], state->rtp_ptr, state->rtp_len); state->rtp_ptr = NULL; state->rtp_len = 0; state->rtp_len_gotten = 0; state->try_periodic = 1; change_state(state, RTP_DATA_START); return 0; } change_state(state, RTP_DATA_CONTINUE); return 1;}static const char *rtsp_cmp = "rtsp/1.0";static int rtsp_get_resp (rtsp_client_t *info, rtp_state_t *state){ int ret; ret = rtsp_get_response(info); if (ret == RTSP_RESPONSE_RECV_ERROR) { change_state(state, RTP_DATA_UNKNOWN); } else { change_state(state, RTP_DATA_START); if (state->receiving_rtsp_response != 0) { /* * Are they waiting ? If so, pop them the return value */ rtsp_thread_ipc_respond(info, ret); state->receiving_rtsp_response = 0; } } return 1;} static int check_rtsp_resp (rtsp_client_t *info, rtp_state_t *state){ int len, blen, ret; len = strlen(rtsp_cmp); blen = rtsp_bytes_in_buffer(info); if (len > blen) { if (info->m_offset_on != 0) { move_end_of_buffer(info, blen); } ret = rtsp_receive_socket(info, info->m_resp_buffer + blen, len - blen, 0, 0); if (ret < 0) return 0; info->m_buffer_len += ret; blen = rtsp_bytes_in_buffer(info); } if (len <= blen) { if (strncasecmp(rtsp_cmp, &info->m_resp_buffer[info->m_offset_on], len) == 0) { //rtsp_debug(LOG_DEBUG, "Found resp"); return (rtsp_get_resp(info, state)); } info->m_offset_on++; change_state(state, RTP_DATA_UNKNOWN); return 0; } return -1;}static int check_rtp_header (rtsp_client_t *info, rtp_state_t *state){ int ix; int blen; blen = rtsp_bytes_in_buffer(info); if (blen < 3) { return -1; } state->header[0] = info->m_resp_buffer[info->m_offset_on]; state->header[1] = info->m_resp_buffer[info->m_offset_on + 1]; state->header[2] = info->m_resp_buffer[info->m_offset_on + 2]; ix = state->header[0] / 2; if ((ix >= MAX_RTP_THREAD_SESSIONS) || !(info->m_callback[ix].rtp_callback_set)) { // header failure info->m_offset_on++; change_state(state, RTP_DATA_UNKNOWN); return 0; } state->rtp_len = (state->header[1] << 8) | state->header[2]; if (state->rtp_len < 1514) { info->m_offset_on += 3; // increment past the header return (get_rtp_packet(info, state)); } // length is most likely incorrect info->m_offset_on++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -