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

📄 rtsp.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*********************************************************************** *    rtsp.c: for downloading via rtsp (Real Time Streaming Protocol) *********************************************************************** * Copyright (C) 2007 metro <me_t_ro@yahoo.com> * * This file is part of msdl, media stream downloader * * This file is based on rtsp implementation of  * mplayer and xine, and includes code from both projects. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. * ***********************************************************************//* * Copyright notice of MPlayer project * which some part of msdl is based on. * (from MPlayer-1.0rc2/stream/realrtsp/.c) *//* * This file was ported to MPlayer from xine CVS rtsp.c,v 1.9 2003/04/10 02:30:48 *//* * Copyright (C) 2000-2002 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA * * * a minimalistic implementation of rtsp protocol, * *not* RFC 2326 compilant yet. * *    2006, Benjamin Zores and Vincent Mussard *      fixed a lot of RFC compliance issues. *//* * Copyright notice of xine-lib project * which some part of msdl is based on. * (from xine-lib-1.1.14/src/input/librtsp/rtsp.c) *//* * Copyright (C) 2000-2003 the xine project * * This file is part of xine, a free video player. * * xine is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * xine 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * a minimalistic implementation of rtsp protocol, * *not* RFC 2326 compilant yet. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <ctype.h>#include <sys/types.h>#include <sys/socket.h>#include "msdl.h"#include "msdllib.h"#include "display.h"#include "network.h"#include "rtsp.h"#include "real.h"#include "rmff.h"#include "asf.h"#include "wmserver.h"const char rtsp_protocol_version[] = "RTSP/1.0";/* defined in real.c */extern const char rtsp_protocol_version[];extern const char real_clientid[];extern const char real_companyid[];extern const char real_useragent[];extern const char real_clientchallenge[];extern const char real_playerstarttime[];extern const char real_transport[];static struct rtsp_ctrl_t *new_rtsp_ctrl_t(void);static void free_rtsp_ctrl_t(struct rtsp_ctrl_t *ctrlt);static int rtsp_recv_header_get(struct stream_t *stream, struct rtsp_header_t *rtsp_hdr);int rtsp_parse_response(struct rtsp_ctrl_t *rtsp_ctrl,			struct rtsp_header_t *rtsp_header);/* * read rtsp stream. filles buffer, and buffer size is 'size'  * *        read cached data from stream->netsock->buffer *        check for to see if network access is necessary *        get chunk(media packet) from network. * *  return value: bytes written to buffer. -1 if error. *                                          0 if buffering */int rtsp_streaming_read(struct stream_t *stream,			uint8_t *buffer, size_t buffer_size){      struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    size_t pos = 0; // how many bytes are in 'buffer'    int ret = 0;    if(buffer_size == 0) {	display(MSDL_ERR,"buffer_size must be bigger than 0\n");	return -1;    }      if(stream_ctrl->write_data_len) { /* there are waiting data to be written */    	if(buffer_size <= stream_ctrl->write_data_len) {	    /*	      buffer_size < stream_ctrl->write_data_len...	      fill buffer, and return.	    */	    memcpy(buffer,stream_ctrl->write_buffer + stream_ctrl->write_pos,		   buffer_size);	    	    stream_ctrl->write_data_len -= buffer_size;	    stream_ctrl->write_pos += buffer_size;	    return buffer_size;	}	else { 	    /*	      stream_ctrl->write_data_len < buffer_size,	      have to read from network.	    */	    memcpy(buffer,stream_ctrl->write_buffer + stream_ctrl->write_pos,		   stream_ctrl->write_data_len);	    pos = stream_ctrl->write_data_len;	    /* and stream_ctrl->write_buffer is empty. */	    stream_ctrl->write_data_len = 0;	    stream_ctrl->write_pos = 0;	}    }        stream_ctrl->write_data_len = 0;    stream_ctrl->write_pos = 0;        /* still have to get data from network. */    if(stream_ctrl->status != STREAMING_FINISHED) { /* not finished */	ret = stream_ctrl->rtsp_ctrl->get_media_packet(stream,buffer + pos,							   buffer_size - pos);    }        if(stream_ctrl->status == STREAMING_RESUME_BUFFERING) {	return 0;    }    else if(ret >= 0) {	return (ret + pos);    }    else {        return -1; /* error */    }}/* * find Content-Length field in rtsp_hdr, and read (and trash) following data * return value:   bytes received and discarded */int rtsp_ignore_data_after_header(struct stream_t *stream,struct rtsp_header_t *rtsp_hdr){    char *field = NULL;    int body_left = 0;        if((field = rtsp_get_field(rtsp_hdr,"Content-Length")) != NULL) {	uint8_t *ignorebuf = NULL;		while(*field == ' ') field++;	body_left = atoi(field);	if(body_left) {	    ignorebuf = xmalloc(body_left);	    read_data(stream,ignorebuf,body_left);	    free(ignorebuf);	}    }    return body_left;}int is_rtsp_response_ok(int status_code){    return ((200 <= status_code) && (status_code <= 299)) ? 1 : 0;}/* * receive rtsp header but ignore its message, etc.. * this function is purely for making code more readable. * *       return value:  what rtsp_recv_header returned */int rtsp_recv_header_ignore_message(struct stream_t *stream){    struct rtsp_header_t *rtsp_hdr = NULL;    int ret = 0;        rtsp_hdr = new_rtsp_header();    ret = rtsp_recv_header(stream,rtsp_hdr);        /* if content-length field, get all following data */    rtsp_ignore_data_after_header(stream,rtsp_hdr);        free_rtsp_header(rtsp_hdr);    return ret;}/* * alloc new rtsp_header_t and set standard fields for send. * this function is purely for making code more readable. * * return value:  what rtsp_recv_header returned (status code: success  -1: failure) */struct rtsp_header_t *new_rtsp_header_with_standard_fields(struct rtsp_ctrl_t *rtsp_ctrl){    struct rtsp_header_t *rtsp_hdr;    rtsp_hdr = new_rtsp_header();    rtsp_set_standard_fields(rtsp_ctrl,rtsp_hdr);        return rtsp_hdr;}    /* * send rtsp_request and free it. * this function is purely for making code more readable. * * return value:  what rtsp_send request returned. (status code: success  -1: failure) */int rtsp_send_request_and_free(struct stream_t *stream,struct rtsp_header_t *rtsp_hdr){    int ret;        ret = rtsp_send_request(stream,rtsp_hdr);    free_rtsp_header(rtsp_hdr);        return ret;}/* * make range string */char *rtsp_make_range_from_timestamp(uint32_t range_ts){    char *rangestr = (char *)xmalloc(256);    snprintf(rangestr,255,"%d.000-",(range_ts / 1000));    return rangestr;}/* * set Range: field to rtsp_hdr. */void rtsp_set_range_field(struct rtsp_header_t *rtsp_hdr,const char *rangestr){    char *buffer = xmalloc(BUFSIZE_1K);    /* range specified */    if(rangestr) {	char *reason = NULL;		if(rtsp_npt_range_valid(rangestr,&reason)) { /* valid */	    snprintf(buffer,BUFSIZE_1K - 1,"Range: npt=%s",rangestr);	}	else {	    char *npt_range_str = NULL;	    npt_range_str = rtsp_range_to_npt_range(rangestr,&reason);	    if(npt_range_str) { /* acceptable   */		snprintf(buffer,BUFSIZE_1K - 1,"Range: npt=%s",npt_range_str);		display(MSDL_VER,			"send \"%s\" for Range\n",			npt_range_str);		free(npt_range_str);	    }	    else {              /* really inacceptable */		strncpy(buffer,"Range: npt=0.000-",BUFSIZE_1K - 1);		display(MSDL_ERR,			"option \"-r %s\" is invalid as rtsp range request\n"			": %s\n"			"send \"%s\" instead\n",			rangestr,reason,buffer);	    }	}    }    else { /* default range, from beginning */	strncpy(buffer,"Range: npt=0.000-",BUFSIZE_1K - 1);    }    rtsp_set_field(rtsp_hdr,buffer);    free(buffer);}/* * set Speed: field to rtsp_hdr. */void rtsp_set_speed_field(struct rtsp_header_t *rtsp_hdr,const char *speedstr){    char *buffer = xmalloc(BUFSIZE_1K);        /* speed specified */    if(speedstr) {	char *reason = NULL;	int  guessed_speed = 0;		if(speed_valid_and_guess(speedstr,&guessed_speed,&reason)) {	    snprintf(buffer,BUFSIZE_1K - 1,"Speed: %s",speedstr);	    	}	else { /* invlalid, use guessed value */	    if(guessed_speed == 0) {		guessed_speed = 1; /* default speed 1.000 */	    }	    snprintf(buffer,BUFSIZE_1K - 1,"Speed: %d.000",guessed_speed);	    display(MSDL_ERR,		    "option \"-s %s\" is invalid as rtsp speed request\n"		    ": %s\n"		    "send \"%s\" instead\n",		    speedstr,reason,buffer);	}    }    else { /* set default speed*/	strncpy(buffer,"Speed: 1.000",BUFSIZE_1K - 1);    }    rtsp_set_field(rtsp_hdr,buffer);    free(buffer);}/* * * str: [ npt-hh ":" npt-mm ":" ] npt-ss [ "." *DIGIT ] | [00h][00m][00s] ["." *DIGIT] *               * return value:    NULL: really inacceptable, such as "0.0a1" *              npt-time: rtsp npt valid string (malloc) */char *rtsp_time_to_npt_time(const char *str,char **reason_ret){    enum {	SEC = 0,	MIN,	HOUR,	DAY,   /* joke */	YEAR,  /* joke */	NUM_COLS,    };        enum {	NOT_SEPARATED = 0,	COLON_SEPARATED,	CHAR_SEPARATED,    };        int i = 0;    int j = 0; /* only to slide sep_time */    int len = strlen(str);    int sep_time_filled[NUM_COLS] = {0};    uint64_t sep_time[NUM_COLS] = {0}; /* separated time */    int separated_way = NOT_SEPARATED;    int met_colon = 0;    uint64_t value = 0;    int npt_acceptable = 1;    char *str_after_dot = "\0";        /* points to empty string by default. includes '.' itself */    char *npt_time = NULL;    char *reason = NULL;    if(!strcmp(str,"now")) {	npt_time = strdup("now");	reason = "";	if(reason_ret) {	    *reason_ret = reason;	}	return npt_time;    }        value = 0;    met_colon = 0;    npt_acceptable = 1;    for(i = 0 ; (i < len) && npt_acceptable ; i++) {	if('0' <= str[i] && str[i] <= '9') {	    value *= 10;	    value += str[i] - '0';	}	else if(str[i] == '.') {	    char *dot_pos = (char *)str + i;	    if((i == 0) || (i == len - 1)) { /* dot was at the beginning or end of string */		reason = "\'.\' at the beginning or end of string";		npt_acceptable = 0;		break;	    }	    i++;	    for(; i < len ; i++) {		if(('0' <= str[i]) && (str[i] <= '9')) {		    continue;		}		else {		    reason = "invalid char after \'.\'";		    npt_acceptable = 0;		    break;		}	    }	    /* string after dot was valid */	    if(npt_acceptable) {		str_after_dot = dot_pos;	    }	}	else if(str[i] == ':') {     /* colon can be a separator */	    if(separated_way == CHAR_SEPARATED) {		reason = "confusing time separator";		npt_acceptable = 0;		break;	    }	    	    separated_way = COLON_SEPARATED;	    if(met_colon < NUM_COLS - 1) { /* separator = column = 1 */				for(j = NUM_COLS - 1; j ; j--) {		    sep_time[j] = sep_time[j - 1]; /* slide */		}		sep_time[0] = value;				met_colon++;		value = 0; /* reset value */		continue;	    }

⌨️ 快捷键说明

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