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

📄 wmserver.c

📁 linux下流媒体下载程序代码
💻 C
📖 第 1 页 / 共 2 页
字号:
    int i = 0;                      /* for various purposes                */    char checkbuf[10];              /* to check if the message is ANNOUCNE */    struct rtsp_header_t *rtsp_hdr = NULL;    int got_cseq = 0;               /* cseq received                */    int status_code = 0;            /* rtsp_hdr status code         */    char *field = NULL;             /* filed pointer for rtsp_hdr   */    int len = 0;                    /* len of description (content length) */    char *description = NULL;       /* description, data of rtsp packet    */    char *buffer = NULL;            /* temp buffer for building req */    struct sdpwms_t *sdpwms = NULL;    struct asf_headerinfo_t* asf_headerinfo = NULL;        buffer = xmalloc(BUFSIZE_1K);    i = recv_data(stream,checkbuf,8);    if(i < 8 || memcmp(checkbuf,"ANNOUNCE",8)) {	goto failed;    }      stream_data_push_back(stream,checkbuf,i); /* push back "ANNOUNCE" */      rtsp_hdr = new_rtsp_header();    rtsp_recv_header(stream,rtsp_hdr);      status_code = rtsp_hdr->status_code;    /* get content length data */    if((field = rtsp_get_field(rtsp_hdr,"Content-Length")) != NULL) {	while(*field == ' ') field++;	len = atoi(field);	    }        if((field = rtsp_get_field(rtsp_hdr,"Cseq")) != NULL) {	while(*field == ' ') field++;	got_cseq = atoi(field);	    }    /*      copy sdp    */    description = xmalloc(len + 1);    len = read_data(stream,description,len);    description[len] = '\0';        free_rtsp_header(rtsp_hdr);      if(status_code != RTSP_STATUS_ANNOUNCE) {	goto failed; /* not likely but have to check this */    }      /*      got annouce packet, and data is in description    */    rtsp_200ok(stream,got_cseq,rtsp_ctrl->session); /* OK (required, according to RFC )*/        wmserver_get_info_from_sdp_string(stream,description,&asf_headerinfo,&sdpwms);        /* Be careful with Cseq: */      /* SETUP */    if(wmserver_rtsp_setup(stream,asf_headerinfo,sdpwms) < 0) {	goto failed;    }	    /* send SET_PARAMETER request to download stream */    if(wmserver_rtsp_set_parameter(stream) < 0) {	goto failed;	    }        /*  send PLAY request to download stream */    if(wmserver_rtsp_play(stream) < 0) {	goto failed;	    }    /*     * here do NOT need to write asf_headerinfo or those stuff     * those are already done in very first protocol initiation.     */    free_sdpwms_t(sdpwms);        free(description);    free(buffer);    return asf_headerinfo;    failed:    if(description) free(description);    if(sdpwms) free_sdpwms_t(sdpwms);    if(asf_headerinfo) free_asf_headerinfo_t(asf_headerinfo);    if(buffer) free(buffer);    return NULL;    }/* * read from media stream. (wmserver rdp packet) *  * fill 'buffer' with data, and buffer size is 'max_size'. * receive one chunk from stream->sock, and fills 'max_size' bytes to buffer. * and if there are more bytes in the chunk, the data is stored to * stream->netsock->buffer. * *    return value: positive value ... bytes written to buffer. *                  0              ... END OF STREAM *                 -1              ... ERROR */int wmserver_rtp_get_media_packet(struct stream_t *stream,				  uint8_t *buffer,size_t max_size){    int ret = 0;    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    uint8_t header[8];        ret = read_data(stream,header,8);    if(ret < 8) {	goto failed;    }        /* skip until it gets media packet */    while(!strncasecmp((char *)header,"SET_",4) ||	  !strncasecmp((char *)header,"GET_",4) ||	  !strncasecmp((char *)header,"OPTI",4) ||	  !strncasecmp((char *)header,"RTSP",4) ||	  !strncasecmp((char *)header,"ANNO",4)) {		stream_data_push_back(stream,header,8); /* push back header */		ret = wmserver_process_header(stream);	if(ret < 0) {	    goto failed;	}	if(ret == 0 && stream_ctrl->status == STREAMING_FINISHED) {	    /* streaming finished (at least it says) */      	    /*	      wait for 2 seconds.. this is necessary becasue	      otherwise it would block when waiting "ANNOUNCE"	    */	    if(stream_check_data(stream,2) > 0) {		struct asf_headerinfo_t *asf_headerinfo = NULL;				if((asf_headerinfo = wmserver_announce_continue(stream))) {		    int ret = 0;		    		    display(MSDL_DBG,"streaming still continues!!\n");		    		    /* write header to write buffer and return... */		    if(asf_headerinfo->asf_header_len <= max_size) { /* everything can go... */			memcpy(buffer,asf_headerinfo->asf_header,			       asf_headerinfo->asf_header_len);			ret = asf_headerinfo->asf_header_len;		    }		    else {			memcpy(buffer,asf_headerinfo->asf_header,max_size);			memcpy(stream_ctrl->write_buffer, asf_headerinfo->asf_header + max_size,			       asf_headerinfo->asf_header_len - max_size);			stream_ctrl->write_data_len = asf_headerinfo->asf_header_len - max_size;			ret = max_size;		    }	  		    /*free_asf_headerinfo_t(asf_headerinfo); this is done in free_rtsp_ctrl_t */		    stream_ctrl->status = STREAMING_REWIND;		    return ret; /* write asf header */		}	    }	    	    /* if no ANNOUCNE, finish streaming */	    display(MSDL_DBG,"finish rtsp streaming\n");	    return 0; /* streaming really finished */	}	else {	    /* streaming still continues */	    ret = read_data(stream,header,8);	    if(ret < 8) {		goto failed;	    }	}    }        ret = wmserver_process_media_packet(stream,header,buffer,max_size);    return ret;  failed:    return -1;    }/* * process rtsp header coming among rtsp wmserver media packet *  * return value:       status code ... normal proceed case *                               0 ... EOF packet *                              -1 ... error */static int wmserver_process_header(struct stream_t *stream){    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    struct rtsp_ctrl_t *rtsp_ctrl = stream_ctrl->rtsp_ctrl;    struct rtsp_header_t *rtsp_hdr = NULL;    int status_code = 0;    size_t bodylen = 0;    uint8_t *body = NULL;    char *field = NULL;    int got_cseq = 0;          /* push back 4 bytes */        rtsp_hdr = new_rtsp_header();    status_code = rtsp_recv_header(stream,rtsp_hdr);    if(status_code < 0) {	goto failed;    }    /* get content length data */    if((field = rtsp_get_field(rtsp_hdr,"Content-Length")) != NULL) {	while(*field == ' ') field++;	bodylen = atoi(field);	body = xmalloc(bodylen);	bodylen = read_data(stream,body,bodylen); /* read rest of data */    }          if((field = rtsp_get_field(rtsp_hdr,"Cseq")) != NULL) {	while(*field == ' ') field++;	got_cseq = atoi(field);	    }        if(!strncasecmp(rtsp_hdr->protocol,"RTSP",4)) {	/* RTSP/1.0 200 OK ... ignore this */		if(got_cseq != rtsp_ctrl->cseq - 1) { /* rtsp_ctrl->cseq increment in send */	    display(MSDL_DBG,"CSeq mismatch: expected %d, got %d",		    rtsp_ctrl->cseq - 1,got_cseq);	}	/* DO NOT send OK back to this */    }    else if(!strncasecmp(rtsp_hdr->protocol,"SET_PARAMETER",13)) { /* SET_PARAMETER */	char *p;	/* EOF message comes here */	if(body && (p = strstr((char *)body,"EOF:"))) { // body must exist <<- fix 1.2.2	    p += 4;	    while(*p == ' ') p++; 	    if((!strncasecmp(p,"true",4))) { /* EOF */	    		display(MSDL_DBG,"End of file packet received\n");		stream_ctrl->status = STREAMING_FINISHED;		free(body);		free_rtsp_header(rtsp_hdr);		return 0;	    }	}	rtsp_200ok(stream,got_cseq,rtsp_ctrl->session);	    }          else {	/* everything else ... just send OK */	rtsp_200ok(stream,got_cseq,rtsp_ctrl->session);    }            if(body)     free(body);    if(rtsp_hdr) free_rtsp_header(rtsp_hdr);    return status_code;  failed:    if(body)     free(body);    if(rtsp_hdr) free_rtsp_header(rtsp_hdr);    return -1;}/* * process wmserver rtsp media packet * return value:   bytes written in buffer, *                                   -1 ... error */static int wmserver_process_media_packet(struct stream_t *stream,uint8_t *header,					 uint8_t *buffer,size_t max_size){    struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl;    int ret = 0;    int i = 0;    uint8_t header2[8];      int size   = 0;       /* size of =in-wma-usable part of= packet */    int flags1 = 0;    int flags2 = 0;    int cc = 0;           /* number of csrc */    uint16_t seq = 0;    uint32_t ts  = 0;    uint32_t ssrc = 0;    /* syncronization source */    uint32_t csrc = 0;    /* contributing source   */    uint8_t  rtp_payload[4];        /* RTSP interleaved frame */    if(header[0] != 0x24) {	display(MSDL_ERR,"wrong rdt/rtp magic : [0x%02x]\n",header[0]);	/* dump header*/	dbgdump(header,8);	display(MSDL_DBG,"\n");	goto failed;    }    size = (header[1] << 16) + (header[2] << 8) + header[3];    /* RTP */    flags1 = header[4];    flags2 = header[5];    cc = (flags1 & 0x0f);    seq = get16_be((uint8_t *)header + 6);    read_data(stream,header2,8);    ts = get32_be((uint8_t *)header2);    ssrc = get32_be((uint8_t *)header2 + 4);    size -= 12;      for(i = 0 ; i < cc ; i++ ) {	read_data(stream,(uint8_t *)&csrc,4);	csrc = be2me_32(csrc);	size -= 4;    }      /* RTP Payload Format Header */    {	int  optionalsize = 0;    /* how many bytes for optional field */	read_data(stream,rtp_payload,4); /* get RTP Payload Format Header */	if(rtp_payload[0] & 0x20) { /* Relative Timestamp (optional) present */	    optionalsize += 4;	}	if(rtp_payload[0] & 0x10) { /* Duration (optional) present   */	    optionalsize += 4;	}	if(rtp_payload[0] & 0x08) { /* LocationId (optional) present */	    optionalsize += 4;	}	if(optionalsize > 0) {	    char optional_fields[16]; /* maximum 12 bytes */	    read_data(stream,optional_fields,optionalsize);	}	size -= 4 + optionalsize;    }    stream_ctrl->packet_count++;    /*      the KEEP-ALIVE packet for every 200 --> otherwise server ends connection    */     if(!(stream_ctrl->packet_count % 200)) {	struct rtsp_header_t *rtsp_hdr;	rtsp_hdr = new_rtsp_header_with_standard_fields(stream_ctrl->rtsp_ctrl);	rtsp_request_get_parameter(rtsp_hdr,stream_ctrl->rtsp_ctrl->mrl);	rtsp_send_request_and_free(stream,rtsp_hdr);    }    /* if buffering (for resuming), do special thing */    if(stream_ctrl->status == STREAMING_RESUME_BUFFERING) {	uint32_t send_time_of_this_packet = 0;		ret = read_data(stream,stream_ctrl->write_buffer,size);		asf_data_packet_get_send_time(stream_ctrl->write_buffer,				      &send_time_of_this_packet);	display(MSDL_DBG,		"target ts: %d [0x%x], current packet ts: %d [0x%x]\n",		stream_ctrl->rtsp_ctrl->resume_start_ts,		stream_ctrl->rtsp_ctrl->resume_start_ts,		send_time_of_this_packet,send_time_of_this_packet);	if(send_time_of_this_packet == stream_ctrl->rtsp_ctrl->resume_start_ts) {	    	    stream_ctrl->status = STREAMING_DOWNLOADING; /* remove resuming flag */	    	    if(max_size > stream_ctrl->packet_length) {  /* go to buffer       */		memcpy(buffer,stream_ctrl->write_buffer,size);		memset(buffer + size,0,stream_ctrl->packet_length - size); /* padding */		stream_ctrl->write_data_len = 0;		stream_ctrl->write_pos = 0;				return stream_ctrl->packet_length;	    }	    else {                                       /* go to write_buffer */		memset(stream_ctrl->write_buffer + size,0,		       stream_ctrl->packet_length - size); /* padding */		memcpy(buffer,stream_ctrl->write_buffer,max_size);		stream_ctrl->write_data_len = stream_ctrl->packet_length - max_size;		stream_ctrl->write_pos = max_size;		return max_size;	    }	    	}	else if(send_time_of_this_packet > stream_ctrl->rtsp_ctrl->resume_start_ts) {	    /* this means resuming failed, because time stamp is different */	    display(MSDL_ERR,		    "resume buffeing: timestamp error\n"		    "                 suggest downloading from beginning\n");	    goto failed;	}	else {	    return 0;	}    } /* buffering case end */        /* store to buffer, or write_buffer */    if(max_size > stream_ctrl->packet_length) {	/* all data can go to buffer --> just do it!! */	ret = read_data(stream,buffer,size);	if(ret <= 0) goto failed;	memset(buffer + size,0,stream_ctrl->packet_length - size); /* padding */	return stream_ctrl->packet_length;    }    else {	/*	  buffer is not enough.. copy max_size data to 	  buffer and the rest goes to stream_ctrl->write_buffer.	*/	ret = read_data(stream,stream_ctrl->write_buffer,size);	if(ret <= 0) goto failed;    	/*	  it is guranteed that stream_ctrl->write_buffer is	  empty when it comes here!	  --> reset stream_ctrl->write_pos and so on...	*/		if(stream_ctrl->packet_length < size) {	    display(MSDL_ERR,"packet_length(%d) is smaller than size(%d)\n",		    stream_ctrl->packet_length,size);	    goto failed; /* this should not happen*/	}	memset(stream_ctrl->write_buffer + size,0,	       stream_ctrl->packet_length - size); /* padding */	memcpy(buffer,stream_ctrl->write_buffer,max_size);    	stream_ctrl->write_data_len = stream_ctrl->packet_length - max_size;	stream_ctrl->write_pos += max_size;    	return max_size;    }      failed:    return -1;}/* * prepare_resuming for wmserver rtsp * return value:     1 ... success *                  -1 ... failed */int wmserver_prepare_resuming(struct stream_t *stream){    /* search local file which has same name with straem*/    uint32_t last_send_time = 0;    uint64_t seek_pos = 0;    int ret = 0;        /*     * find same file name     */        ret = asf_get_npt_of_last_packet(stream->localfile,&last_send_time,&seek_pos);    if(ret < 0) {	goto failed;    }    if((last_send_time / 1000) <  MINIMUM_RESUME_START_TIME) {	display(MSDL_ERR,		"file \"%s\" has only %d sec, just start from beginning\n",		stream->localfile,last_send_time / 1000);	goto failed;    }            stream->stream_ctrl->rtsp_ctrl->resume_start_ts = last_send_time;        /* free dlotps->range */    if(stream->dlopts->range) {	free(stream->dlopts->range);    }    stream->dlopts->range =	rtsp_make_range_from_timestamp(last_send_time - RESUME_BUFFERING_TIME);    stream->resumeinfo->resume_start_offset = seek_pos;    stream->resumeinfo->resume_req_success = 1;    display(MSDL_DBG,	    "wms resume: start ts: %d [0x%x]   pos: %lld [0x%llx]\n",	    last_send_time,last_send_time,seek_pos,seek_pos);    return 1;  failed:    stream->resumeinfo->resume_start_offset = 0; /* don't check request result */    stream->resumeinfo->resume_req_success = 0;    return -1;}

⌨️ 快捷键说明

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