📄 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 + -