📄 rtsp_command.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / IETF RTP/RTSP/SDP sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/internal/ietf_dev.h>#include <gpac/token.h>GF_EXPORTGF_RTSPCommand *gf_rtsp_command_new(){ GF_RTSPCommand *tmp; GF_SAFEALLOC(tmp, GF_RTSPCommand); tmp->Xtensions = gf_list_new(); tmp->Transports = gf_list_new(); return tmp;}#define COM_FREE_CLEAN(hdr) if (com->hdr) free(com->hdr); \ com->hdr = NULL;GF_EXPORTvoid gf_rtsp_command_reset(GF_RTSPCommand *com){ GF_RTSPTransport *trans; GF_X_Attribute *att; if (!com) return; //free all headers COM_FREE_CLEAN(Accept); COM_FREE_CLEAN(Accept_Encoding); COM_FREE_CLEAN(Accept_Language); COM_FREE_CLEAN(Authorization); COM_FREE_CLEAN(Cache_Control); COM_FREE_CLEAN(Conference); COM_FREE_CLEAN(Connection); COM_FREE_CLEAN(From); COM_FREE_CLEAN(Proxy_Authorization); COM_FREE_CLEAN(Proxy_Require); COM_FREE_CLEAN(Referer); COM_FREE_CLEAN(Session); COM_FREE_CLEAN(User_Agent); COM_FREE_CLEAN(body); COM_FREE_CLEAN(service_name); COM_FREE_CLEAN(ControlString); COM_FREE_CLEAN(method); //this is for server only, set to OK by default com->StatusCode = NC_RTSP_OK; com->user_data = NULL; com->Bandwidth = com->Blocksize = com->Content_Length = com->CSeq = 0; com->Scale = com->Speed = 0.0; if (com->Range) free(com->Range); com->Range = NULL; while (gf_list_count(com->Transports)) { trans = (GF_RTSPTransport *) gf_list_get(com->Transports, 0); gf_list_rem(com->Transports, 0); gf_rtsp_transport_del(trans); } while (gf_list_count(com->Xtensions)) { att = (GF_X_Attribute*)gf_list_get(com->Xtensions, 0); gf_list_rem(com->Xtensions, 0); free(att->Name); free(att->Value); free(att); }}GF_EXPORTvoid gf_rtsp_command_del(GF_RTSPCommand *com){ if (!com) return; gf_rtsp_command_reset(com); gf_list_del(com->Xtensions); gf_list_del(com->Transports); free(com);}GF_Err RTSP_WriteCommand(GF_RTSPSession *sess, GF_RTSPCommand *com, unsigned char *req_buffer, unsigned char **out_buffer, u32 *out_size){ u32 i, cur_pos, size, count; char *buffer, temp[50]; GF_RTSPTransport *trans; GF_X_Attribute *att; *out_buffer = NULL; size = RTSP_WRITE_STEPALLOC; buffer = (char *) malloc(size); cur_pos = 0; //request RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, req_buffer); //then all headers RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept", com->Accept); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept-Encoding", com->Accept_Encoding); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Accept-Language", com->Accept_Language); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Authorization", com->Authorization); if (com->Bandwidth) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Bandwidth: "); RTSP_WRITE_INT(buffer, size, cur_pos, com->Bandwidth, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } if (com->Blocksize) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Blocksize: "); RTSP_WRITE_INT(buffer, size, cur_pos, com->Blocksize, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Cache-Control", com->Cache_Control); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Conference", com->Conference); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Connection", com->Connection); //if we have a body write the content length if (com->body) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Content-Length: "); RTSP_WRITE_INT(buffer, size, cur_pos, strlen(com->body), 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } //write the CSeq - use the SESSION CSeq RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "CSeq: "); RTSP_WRITE_INT(buffer, size, cur_pos, sess->CSeq, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); RTSP_WRITE_HEADER(buffer, size, cur_pos, "From", com->From); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Proxy-Authorization", com->Proxy_Authorization); RTSP_WRITE_HEADER(buffer, size, cur_pos, "Proxy-Require", com->Proxy_Require); //Range, only NPT if (com->Range && !com->Range->UseSMPTE) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Range: npt="); RTSP_WRITE_FLOAT(buffer, size, cur_pos, com->Range->start); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); if (com->Range->end > com->Range->start) { RTSP_WRITE_FLOAT(buffer, size, cur_pos, com->Range->end); } RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Referer", com->Referer); if (com->Scale != 0.0) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Scale: "); RTSP_WRITE_FLOAT(buffer, size, cur_pos, com->Scale); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "Session", com->Session); if (com->Speed != 0.0) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Speed: "); RTSP_WRITE_FLOAT(buffer, size, cur_pos, com->Speed); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } //transport info count = gf_list_count(com->Transports); if (count) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "Transport: "); for (i=0; i<count; i++) { //line separator for headers if (i) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n ,"); trans = (GF_RTSPTransport *) gf_list_get(com->Transports, i); //then write the structure RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->Profile); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, (trans->IsUnicast ? ";unicast" : ";multicast")); if (trans->destination) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";destination="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->destination); } if (trans->source) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";source="); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->source); } if (trans->IsRecord) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";mode=RECORD"); if (trans->Append) RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";append"); } if (trans->IsInterleaved) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";interleaved="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->rtpID, 0); if (trans->rtcpID != trans->rtpID) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->rtcpID, 0); } } //multicast specific if (!trans->IsUnicast) { if (trans->MulticastLayers) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";layers="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->MulticastLayers, 0); } if (trans->TTL) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";ttl="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->TTL, 0); } } if (trans->port_first) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, trans->IsUnicast ? ";server_port=" : ";port="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->port_first, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->port_last, 0); } if (trans->IsUnicast && trans->client_port_first) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";client_port="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->client_port_first, 0); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "-"); RTSP_WRITE_INT(buffer, size, cur_pos, trans->client_port_last, 0); } if (trans->SSRC) { RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, ";ssrc="); RTSP_WRITE_INT(buffer, size, cur_pos, trans->SSRC, 0); } } //done with transport RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); } RTSP_WRITE_HEADER(buffer, size, cur_pos, "User-Agent", com->User_Agent); //eXtensions count = gf_list_count(com->Xtensions); for (i=0; i<count; i++) { att = (GF_X_Attribute *) gf_list_get(com->Xtensions, i); RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "x-"); RTSP_WRITE_HEADER(buffer, size, cur_pos, att->Name, att->Value); } //the end of header RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); //then body RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, com->body); //the end of message ? to check, should not be needed...// RTSP_WRITE_ALLOC_STR(buffer, size, cur_pos, "\r\n"); *out_buffer = (unsigned char *)buffer; *out_size = strlen(buffer); return GF_OK;}//format a DESCRIBE, SETUP, PLAY or PAUSE on a session//YOUR COMMAND MUST BE FORMATTED ACCORDINGLY //sCtrl contains a control string if needed, formating the REQUEST as server_url/service_name/sCtrlGF_EXPORTGF_Err gf_rtsp_send_command(GF_RTSPSession *sess, GF_RTSPCommand *com){ GF_Err e; char *sCtrl; const char *rad; u32 size; char buffer[1024], *result, *body; if (!com || !com->method) return GF_BAD_PARAM; sCtrl = com->ControlString; //NB: OPTIONS is not sent this way if (strcmp(com->method, GF_RTSP_DESCRIBE) && strcmp(com->method, GF_RTSP_ANNOUNCE) && strcmp(com->method, GF_RTSP_GET_PARAMETER) && strcmp(com->method, GF_RTSP_SET_PARAMETER) && strcmp(com->method, GF_RTSP_SETUP) && strcmp(com->method, GF_RTSP_PLAY) && strcmp(com->method, GF_RTSP_PAUSE) && strcmp(com->method, GF_RTSP_RECORD) && strcmp(com->method, GF_RTSP_REDIRECTE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -