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

📄 rtsp_client.c

📁 最基本的rtsp client 程序
💻 C
字号:
/*--------------------------------------------------------	COPYRIGHT 2007 (C) DVN (Holdings) Ltd (Hongkong)	AUTHOR:		wangry@dvnchina.com	PURPOSE:	kasenna simple rtsp lib	CREATED:	2007-12-10	MODIFICATION HISTORY	Date        By     Details	----------  -----  ---------------------------------------------------------------*/#include <time.h>#include <semaphore.h>#include <pthread.h>#include "rtsp.h"#include "rtsp_client.h"#include "rtsp_sock.h"#include "rtsp_command.h"#include "rtsp_response.h"static rtsp_client_t* rtsp_client = 0;static rtsp_callback_func_t rtsp_callback_func = 0;/*-------------------------------------------------------	commone function*/static pthread_mutex_t  resp_lock = PTHREAD_MUTEX_INITIALIZER;#define RESP_LOCK()		pthread_mutex_lock (&resp_lock)#define RESP_UNLOCK()	pthread_mutex_unlock (&resp_lock)unsigned int get_time(){	struct timeval tv;	memset(&tv, 0, sizeof(tv));	gettimeofday(&tv, 0);	return tv.tv_sec*1000 + tv.tv_usec/1000;}static sem_t resp_sem;void resp_sem_create(){	sem_init(&resp_sem, 0, 0);}void resp_sem_send(){	sem_post(&resp_sem);}int resp_sem_wait(int timeout){	struct timeval   now;	struct timespec  ts;	gettimeofday(&now, 0);	ts.tv_sec  = now.tv_sec + timeout/1000 ;	ts.tv_nsec = now.tv_usec * 1000 + timeout%1000*1000000;	ts.tv_sec  += ts.tv_nsec/1000000000;	ts.tv_nsec = ts.tv_nsec%1000000000;	return sem_timedwait(&resp_sem, &ts);}void resp_sem_destroy(){	sem_destroy(&resp_sem);}static int rtsp_check_url (rtsp_client_t *client, const char *url){	const char *str;	const char *nextslash;	const char *nextcolon;	int hostlen;	str = url;	if (strncmp("rtsp://", url, strlen("rtsp://")) == 0)		str += strlen("rtsp://");	else		return -1;	nextslash = strchr(str, '/');	nextcolon = strchr(str, ':');	if (nextslash != 0 || nextcolon != 0)	{		if (nextcolon != 0 && (nextcolon < nextslash || nextslash == 0))		{			hostlen = nextcolon - str;			nextcolon++;			client->server_port = 0;			while (isdigit(*nextcolon))			{				client->server_port *= 10;				client->server_port += *nextcolon - '0';				nextcolon++;			}			if (client->server_port == 0 || (*nextcolon != '/' && *nextcolon != '\0'))				return -1;		}		else			hostlen = nextslash - str;		if (hostlen == 0)			return -1;		client->server_name = malloc(hostlen + 1);		if (client->server_name == 0)			return -1;		memcpy(client->server_name, str, hostlen);		client->server_name[hostlen] = '\0';	}	else	{		if (*str == '\0')			return -1;		client->server_name = strdup(str);	}	client->url = strdup(url);	if (client->server_port == 0)		client->server_port = 554;	RTSP_INFO("server ip=%s port=%d url=%s\n", client->server_name, client->server_port, client->url);	return 0;}static void rtsp_free_client (rtsp_client_t* client){	rtsp_close_socket(client);	CHECK_AND_FREE(client->url);	CHECK_AND_FREE(client->server_name);	CHECK_AND_FREE(client->session);	free(client);}static rtsp_client_t *rtsp_create_client (const char *url){	rtsp_client_t *client;	int ret;	client = malloc(sizeof(rtsp_client_t));	if (client == 0)	{		RTSP_ERR("malloc rtsp client fail\n");		return 0;	}	memset(client, 0, sizeof(rtsp_client_t));	client->recv_timeout = 0;	client->next_cseq = 1;	client->server_socket = -1;	ret = rtsp_check_url(client, url);	if (ret != 0)	{		RTSP_ERR("rtsp url is error, url=%s\n", url);		rtsp_free_client(client);		return 0;	}	if (rtsp_create_socket(client) != 0)	{		rtsp_free_client(client);		return 0;	}	return client;}pthread_t thread_id;int thread_quit_flag = 0;rtsp_resp_t* asyn_response = 0;static void rtsp_recv_thread(void* param){	char data[2048];	int track;	int state;	int len;	int ret;	rtsp_resp_t* resp = 0;	state = 0;		while (!thread_quit_flag)	{		if (state == 0)		{			if (resp)			{				clear_response(resp);			}			else			{				resp = (rtsp_resp_t*)malloc(sizeof(rtsp_resp_t));				memset(resp, 0, sizeof(rtsp_resp_t));			}			ret = rtsp_recv_response(rtsp_client, resp);			if (ret == 0)			{				if (strcmp(resp->caption, "RTSP/1.0") == 0)				{					RESP_LOCK();					if (asyn_response)					{						free_response(asyn_response);						asyn_response = 0;						RTSP_ALERT("asyn_response have not used\n");					}					asyn_response = resp;					resp = 0;					RESP_UNLOCK();										resp_sem_send();				}				else				{					rtsp_callback_func(0, 0, 0);					RTSP_INFO("get s->c message: %s\n", resp->caption);				}				state = 1;			}		}		else		{			ret = rtsp_recv_interleave_data(rtsp_client, data, &len, &track);			if (ret == 0)			{				rtsp_callback_func(1, data, len);			}			else if (ret == -2)			{				state = 0;				RTSP_INFO("find rtsp message\n");			}			else			{			}		}	}}static rtsp_resp_t* rtsp_get_asyn_response(){	rtsp_resp_t* ret = 0;		if (resp_sem_wait(2000) != 0)	{		RTSP_INFO("wait response semphore fail\n");		return 0;	}		RESP_LOCK();	ret = asyn_response;	asyn_response = 0;	RESP_UNLOCK();	return ret;}static int rtsp_comm_check_resp(rtsp_resp_t* resp){	rtsp_client->next_cseq++;	if (strcmp(resp->caption, "RTSP/1.0") != 0)	{		RTSP_ALERT("rtsp respond is quit message, msg=%s\n", resp->caption);		return -1;	}		if (strcmp(resp->retcode, "200") != 0)	{		RTSP_ALERT("rtsp respond code(%s) != 200\n", resp->retcode);		return -1;	}	if (resp->cseq + 1 != rtsp_client->next_cseq)	{		RTSP_ALERT("rtsp respond cseq[%d] != send cseq[%d]\n", rtsp_client->next_cseq, resp->cseq);		return -1;	}		return 0;}int rtsp_open(char* url, int* clip_len, rtsp_callback_func_t func){	rtsp_command_t cmd;	rtsp_resp_t resp;	int ret;	rtsp_client = rtsp_create_client(url);	if (rtsp_client == 0)	{		return -1;	}		/*------------------------------------------------------------	describe													*/	ret = -1;	memset(&cmd, 0, sizeof(cmd));	cmd.accept = "application/sdp";	if (rtsp_send_cmd("DESCRIBE", rtsp_client, &cmd, "") == 0)	{		memset(&resp, 0, sizeof(resp));		if (rtsp_recv_response(rtsp_client, &resp) == 0)		{			if (rtsp_comm_check_resp(&resp) == 0)			{				*clip_len = simple_parse_sdp(resp.body);				ret = 0;			}			clear_response(&resp);		}	}	if (ret != 0)	{		rtsp_free_client(rtsp_client);		rtsp_client = 0;		return -1;	}	/*------------------------------------------------------------	setup														*/	ret = -1;	memset(&cmd, 0, sizeof(cmd));	cmd.transport = "MP2T/TCP";	if (rtsp_send_cmd("SETUP", rtsp_client, &cmd, "/trackID=0") == 0)	{		memset(&resp, 0, sizeof(resp));		if (rtsp_recv_response(rtsp_client, &resp) == 0)		{			if (rtsp_comm_check_resp(&resp) == 0)			{				rtsp_client->session = strdup(resp.session);				ret = 0;			}			clear_response(&resp);		}	}	if (ret != 0)	{		rtsp_free_client(rtsp_client);		rtsp_client = 0;			return -1;	}		/*------------------------------------------------------------	start recv thread											*/	thread_quit_flag = 0;	asyn_response = 0;	rtsp_callback_func = func;	resp_sem_create();	pthread_create(&thread_id, 0, (void*)rtsp_recv_thread, 0);	return 0;}int	rtsp_play(int pos){	if (rtsp_client)	{		char str[20];		rtsp_command_t cmd;		memset(&cmd, 0, sizeof(cmd));		cmd.session = rtsp_client->session;		if (pos != -1)		{			sprintf(str, "npt=%d-", pos);			cmd.range = str;		}				if (rtsp_send_cmd("PLAY", rtsp_client, &cmd, "") == 0)		{			rtsp_resp_t* resp = rtsp_get_asyn_response();			if (resp != 0)			{				if (rtsp_comm_check_resp(resp) == 0)				{					free_response(resp);					return 0;				}				free_response(resp);			}		}	}	return -1;}int	rtsp_pause(){	if (rtsp_client)	{		rtsp_command_t cmd;		memset(&cmd, 0, sizeof(cmd));		cmd.session = rtsp_client->session;				if (rtsp_send_cmd("PAUSE", rtsp_client, &cmd, "") == 0)		{			rtsp_resp_t* resp = rtsp_get_asyn_response();			if (resp != 0)			{				if (rtsp_comm_check_resp(resp) == 0)				{					free_response(resp);					return 0;				}				free_response(resp);			}		}	}	return -1;}int rtsp_trip(int mode){	if (rtsp_client)	{		rtsp_command_t cmd;		memset(&cmd, 0, sizeof(cmd));		cmd.session = rtsp_client->session;		cmd.range = "npt= - ";		cmd.scale = mode;				if (rtsp_send_cmd("PLAY", rtsp_client, &cmd, "") == 0)		{			rtsp_resp_t* resp = rtsp_get_asyn_response();			if (resp != 0)			{				if (rtsp_comm_check_resp(resp) == 0)				{					free_response(resp);					return 0;				}				free_response(resp);			}		}	}	return -1;}void rtsp_close(){	if (rtsp_client)	{		if (rtsp_client->server_socket != -1 && rtsp_client->net_busy != 1)		{			rtsp_command_t cmd;			memset(&cmd, 0, sizeof(cmd));			cmd.session = rtsp_client->session;						if (rtsp_send_cmd("TEARDOWN", rtsp_client, &cmd, "") == 0)			{				rtsp_resp_t* resp = rtsp_get_asyn_response();				if (resp != 0)				{					if (rtsp_comm_check_resp(resp) == 0)					{						RTSP_INFO("Normal Quit Rtsp Stack\n");					}					free_response(resp);				}			}		}		/*delete receive thread*/		thread_quit_flag = 1;		pthread_join(thread_id, 0);		resp_sem_destroy();		if (asyn_response)		{			free_response(asyn_response);		}				rtsp_free_client(rtsp_client);		rtsp_client = 0;	}}int rtsp_keepalive(){	if (rtsp_client)	{		rtsp_command_t cmd;		memset(&cmd, 0, sizeof(cmd));		cmd.session = rtsp_client->session;				if (rtsp_send_cmd("OPTIONS", rtsp_client, &cmd, "") == 0)		{			rtsp_resp_t* resp = rtsp_get_asyn_response();			if (resp != 0)			{				if (rtsp_comm_check_resp(resp) == 0)				{					free_response(resp);					return 0;				}				free_response(resp);			}		}	}	return -1;}int rtsp_get_position(){	if (rtsp_client)	{		rtsp_command_t cmd;		memset(&cmd, 0, sizeof(cmd));		cmd.session = rtsp_client->session;				if (rtsp_send_cmd("PLAY", rtsp_client, &cmd, "") == 0)		{			rtsp_resp_t* resp = rtsp_get_asyn_response();			if (resp != 0)			{				if (rtsp_comm_check_resp(resp) == 0)				{					int len;					len = simple_parse_range(resp->range);					free_response(resp);					return len;				}				free_response(resp);			}		}	}		return 0;}

⌨️ 快捷键说明

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