📄 real.c
字号:
stream_data_push_back(stream,header,8); /* push back header */ ret = real_process_header(stream); if(ret < 0) { goto failed; } ret = read_data(stream,header,8); if(ret < 8) { goto failed; } } ret = real_process_media_packet(stream,header,buffer,max_size); return ret; failed: return -1;}/* * process rtsp header coming among rtsp real media packet * * return value: status code ... normal proceed case * 0 ... EOF packet (not possible) * -1 ... error */static int real_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; int bodylen = 0; uint8_t *body = NULL; char *field = NULL; int got_cseq = 0; 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); } /* get Cseq, for sending OK back */ 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 */ /* somehow RTSP message reply can be found among rdt messages. send nothing. */ if(!got_cseq == rtsp_ctrl->cseq - 1) { display(MSDL_DBG,"CSeq mismatch: expected %d, got %d", rtsp_ctrl->cseq - 1,got_cseq); } /* DO NOT send RTSP OK */ } else { /* not RTSP, whatever it is, send OK would be just fine */ rtsp_200ok(stream,got_cseq,rtsp_ctrl->session); } if(rtsp_hdr) free_rtsp_header(rtsp_hdr); if(body) free(body); return status_code; failed: if(body) free(body); if(rtsp_hdr) free_rtsp_header(rtsp_hdr); return -1;}static int real_process_media_packet(struct stream_t *stream,uint8_t *header, uint8_t *buffer,size_t max_size){ int ret = 0; struct stream_ctrl_t *stream_ctrl = stream->stream_ctrl; struct rmff_pheader_t ph = {0}; int size = 0; int seq = 0; int flags1 = 0,flags2 = 0; uint32_t ts = 0; if(header[0] != 0x24) { display(MSDL_ERR,"wrong rdt 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]; flags1 = header[4]; if((flags1!=0x40) && (flags1!=0x42)) { display(MSDL_DBG,"wrong rdt flags1 : [0x%02x]\n",flags1); if(header[6] == 0x06) { display(MSDL_DBG,"got end of stream packet\n"); stream_ctrl->status = STREAMING_FINISHED; return 0; } header[0] = header[5]; header[1] = header[6]; header[2] = header[7]; ret = read_data(stream,header + 3,5); if(ret < 5) goto failed; ret = read_data(stream,header + 4,4); if(ret < 4) goto failed; flags1 = header[4]; size -= 9; } flags2 = header[7]; seq = (header[5] << 8) + header[6]; ret = read_data(stream,header,6); if(ret < 6) goto failed; ts = get32_be(header); stream_ctrl->packet_count++; display(MSDL_DBG,"ts:%u size:%u, flags1:0x%02x, seq:%d, flags2:%x\n", ts,size,flags1,seq,flags2); size += 2; ph.object_version = 0; ph.length = size; ph.stream_number = (flags1>>1) & 1; ph.timestamp = ts; ph.reserved = 0; if((flags2 & 1) == 0 && (stream_ctrl->rtsp_ctrl->prev_ts != ts || stream_ctrl->rtsp_ctrl->prev_stream_number != ph.stream_number)) { stream_ctrl->rtsp_ctrl->prev_ts = ts; stream_ctrl->rtsp_ctrl->prev_stream_number = ph.stream_number; ph.flags = 2; } else { ph.flags = 0; } /* * Keep Alive SET_PARAMETER */ /*if(!(stream_ctrl->packet_count % 200)) { struct rtsp_header_t *rtsp_hdr; rtsp_hdr = new_rtsp_header_with_standard_fields(stream_ctrl->rtsp_ctrl); if(stream->dlopts->bandwidth) { char *buffer = xmalloc(BUFSIZE_1K); snprintf(buffer,BUFSIZE_1K - 1, "SetDeliveryBandwidth: Bandwidth=%d;BackOff=0",stream->dlopts->bandwidth); rtsp_set_field(rtsp_hdr,buffer); free(buffer); } rtsp_request_set_parameter(rtsp_hdr,stream_ctrl->rtsp_ctrl->mrl); rtsp_send_request_and_free(stream,rtsp_hdr); }*/ /* if buffering, do special thing */ if(stream_ctrl->status == STREAMING_RESUME_BUFFERING) { 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, ph.timestamp,ph.timestamp); if(ph.timestamp == stream_ctrl->rtsp_ctrl->resume_start_ts) { stream_ctrl->status = STREAMING_DOWNLOADING; /* fallthrouh */ } else { int ret = 0; ret = read_data(stream,stream_ctrl->write_buffer,size - 12); /* trash data */ if(ret <= 0) goto failed; return 0; } } if(max_size > size) { /* all data can go to buffer --> just do it!! */ rmff_dump_pheader(&ph,buffer); size -= 12; ret = read_data(stream,buffer + 12,size); if(ret <= 0) goto failed; return ret + 12; } else { /* buffer is not enough.. copy max_size data to buffer and the rest goes to netsock->buffer. */ rmff_dump_pheader(&ph,stream_ctrl->write_buffer); ret = read_data(stream,stream_ctrl->write_buffer + 12,size - 12); if(ret <= 0) goto failed; /* it is guranteed that netsock->buffer is empty when it comes here! --> reset stream_ctrl->write_pos and so on... */ memcpy(buffer,stream_ctrl->write_buffer,max_size); stream_ctrl->write_data_len = size - max_size; stream_ctrl->write_pos = max_size; return max_size; } failed: return -1;}/* * prepare_resuming for real rtsp * return value: 1 ... success * -1 ... failed */int real_prepare_resuming(struct stream_t *stream){ uint32_t last_send_time = 0; uint64_t seek_pos = 0; int ret = 0; ret = real_get_last_npt_of_file(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; 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, "real 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; stream->resumeinfo->resume_req_success = 0; return -1;}/* * get info for resuming * @send_time : last packet npt (out) * @seek_offset: last packet offset (out) * return value: 1 ... success * -1 ... failure */int real_get_last_npt_of_file(char *local_filename,uint32_t *send_time,uint64_t *seek_offset){ FILE *lfp = NULL; uint32_t header_buffer_size = 400; uint32_t header_buffer_filled = 0; uint8_t *rmff_header_buffer = NULL; int ret = 0; uint64_t file_size = 0; uint64_t rmff_data_start_pos = 0; uint64_t curpos = 0; uint8_t phbuf[18]; struct rmff_pheader_t ph = {0}; uint32_t last_ts = 0,this_ts = 0; uint64_t last_ts_offset = 0; if((lfp = fopen(local_filename,"rb")) == NULL) { display(MSDL_ERR, "resume \"%s\" : cannot open file for resume\n",local_filename); goto failed; } rmff_header_buffer = (uint8_t *)xmalloc(header_buffer_size); /* 1st read */ ret = fread(rmff_header_buffer,sizeof(uint8_t),header_buffer_size,lfp); header_buffer_filled = ret; if(ret < header_buffer_size) { if(ferror(lfp)) { display(MSDL_ERR,"resume \"%s\": cannot read file \n",local_filename); } else { display(MSDL_ERR,"resume \"%s\": too small for resume\n",local_filename); } /* couldn't read, or just only very small amount of data in file*/ goto failed; } if(get32_be(rmff_header_buffer) != RMF_TAG) { /* not the rmff file */ display(MSDL_ERR,"resume \"%s\": not an real file\n",local_filename); goto failed; } ret = get_filesize(local_filename,&file_size); if(ret < 0) { /* stat() failed */ goto failed; } rmff_data_start_pos = get32_be(rmff_header_buffer + 60) + 18; last_ts = 0; for(curpos = rmff_data_start_pos; curpos + sizeof(struct rmff_pheader_t) <= file_size;) { fseek(lfp,curpos,SEEK_SET); ret = fread(phbuf,sizeof(uint8_t),sizeof(struct rmff_pheader_t),lfp); rmff_read_pheader(phbuf,&ph); if(ret < sizeof(struct rmff_pheader_t)) { display(MSDL_ERR,"resume \"%s\": pheader read error",local_filename); goto failed; } this_ts = ph.timestamp; /* printf("this_ts = %d [%x] ph_length = %d %x,cur:%x last:%x (%d)\n", this_ts,this_ts, ph.length,ph.length, curpos, last_ts_offset,last_ts_offset); */ if(this_ts > last_ts) { /* renew ts */ last_ts = this_ts; last_ts_offset = curpos; this_ts = 0; } curpos += ph.length; } fclose(lfp); free(rmff_header_buffer); *send_time = last_ts; *seek_offset = last_ts_offset; return 1; failed: if(lfp) fclose(lfp); if(rmff_header_buffer) free(rmff_header_buffer); *send_time = 0; *seek_offset = 0; return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -