📄 real.c
字号:
/* MLTI chunk should begin with MLTI */ if ((mlti_chunk[0] != 'M') ||(mlti_chunk[1] != 'L') ||(mlti_chunk[2] != 'T') ||(mlti_chunk[3] != 'I')) { lprintf("MLTI tag not detected, copying data\n"); memcpy(*out, mlti_chunk, mlti_size); return mlti_size; } mlti_chunk+=4; /* next 16 bits are the number of rules */ numrules=BE_16(mlti_chunk); if (selection >= numrules) return 0; /* now <numrules> indices of codecs follows */ /* we skip to selection */ mlti_chunk+=(selection+1)*2; /* get our index */ codec=BE_16(mlti_chunk); /* skip to number of codecs */ mlti_chunk+=(numrules-selection)*2; /* get number of codecs */ numrules=BE_16(mlti_chunk); if (codec >= numrules) { lprintf("codec index >= number of codecs. %i %i\n", codec, numrules); return 0; } mlti_chunk+=2; /* now seek to selected codec */ for (i=0; i<codec; i++) { size=BE_32(mlti_chunk); mlti_chunk+=size+4; } size=BE_32(mlti_chunk); memcpy(*out, mlti_chunk+4, size); return size;}/* * looking at stream description. */rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) { sdpplin_t *desc = NULL; rmff_header_t *header = NULL; char *buf = NULL; int len, i; int max_bit_rate=0; int avg_bit_rate=0; int max_packet_size=0; int avg_packet_size=0; int duration=0; if( !data ) return NULL; desc=sdpplin_parse(data); if( !desc ) return NULL; buf= (char *)malloc(sizeof(char)*2048); if( !buf ) goto error; header = (rmff_header_t*)malloc(sizeof(rmff_header_t)); if( !header ) goto error; memset(header, 0, sizeof(rmff_header_t)); header->fileheader=rmff_new_fileheader(4+desc->stream_count); header->cont=rmff_new_cont( desc->title, desc->author, desc->copyright, desc->abstract); header->data=rmff_new_dataheader(0,0); if( !header->data ) goto error; header->streams = (rmff_mdpr_t**) malloc(sizeof(rmff_mdpr_t*)*(desc->stream_count+1)); if( !header->streams ) goto error; memset(header->streams, 0, sizeof(rmff_mdpr_t*)*(desc->stream_count+1)); lprintf("number of streams: %u\n", desc->stream_count); for (i=0; i<desc->stream_count; i++) { int j=0; int n; char b[64]; int rulematches[16]; lprintf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth); n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches); for (j=0; j<n; j++) { lprintf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id); sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]); strcat(*stream_rules, b); } if (!desc->stream[i]->mlti_data) { len = 0; free( buf ); buf = NULL; } else len=select_mlti_data(desc->stream[i]->mlti_data, desc->stream[i]->mlti_data_size, rulematches[0], &buf); header->streams[i]=rmff_new_mdpr( desc->stream[i]->stream_id, desc->stream[i]->max_bit_rate, desc->stream[i]->avg_bit_rate, desc->stream[i]->max_packet_size, desc->stream[i]->avg_packet_size, desc->stream[i]->start_time, desc->stream[i]->preroll, desc->stream[i]->duration, desc->stream[i]->stream_name, desc->stream[i]->mime_type, len, buf); if( !header->streams[i] ) goto error; duration=MAX(duration,desc->stream[i]->duration); max_bit_rate+=desc->stream[i]->max_bit_rate; avg_bit_rate+=desc->stream[i]->avg_bit_rate; max_packet_size=MAX(max_packet_size, desc->stream[i]->max_packet_size); if (avg_packet_size) avg_packet_size=(avg_packet_size + desc->stream[i]->avg_packet_size) / 2; else avg_packet_size=desc->stream[i]->avg_packet_size; } if (*stream_rules && strlen(*stream_rules) && (*stream_rules)[strlen(*stream_rules)-1] == ',') (*stream_rules)[strlen(*stream_rules)-1]=0; /* delete last ',' in stream_rules */ header->prop=rmff_new_prop( max_bit_rate, avg_bit_rate, max_packet_size, avg_packet_size, 0, duration, 0, 0, 0, desc->stream_count, desc->flags); if( !header->prop ) goto error; rmff_fix_header(header); if( desc ) sdpplin_free( desc ); free( buf ); return header;error: if( desc ) sdpplin_free( desc ); if( header ) rmff_free_header( header ); free( buf ); return NULL;}int real_get_rdt_chunk_header(rtsp_client_t *rtsp_session, rmff_pheader_t *ph) { int n=1; uint8_t header[8]; int size; int flags1; int unknown1; uint32_t ts; n=rtsp_read_data(rtsp_session, header, 8); if (n<8) return 0; if (header[0] != 0x24) { lprintf("rdt chunk not recognized: got 0x%02x\n", header[0]); return 0; } size=(header[1]<<16)+(header[2]<<8)+(header[3]); flags1=header[4]; if ((flags1!=0x40)&&(flags1!=0x42)) { lprintf("got flags1: 0x%02x\n",flags1); if (header[6]==0x06) { lprintf("got end of stream packet\n"); return 0; } header[0]=header[5]; header[1]=header[6]; header[2]=header[7]; n=rtsp_read_data(rtsp_session, header+3, 5); if (n<5) return 0; lprintf("ignoring bytes:\n"); n=rtsp_read_data(rtsp_session, header+4, 4); if (n<4) return 0; flags1=header[4]; size-=9; } unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]); n=rtsp_read_data(rtsp_session, header, 6); if (n<6) return 0; ts=BE_32(header);#if 0 lprintf("ts: %u size: %u, flags: 0x%02x, unknown values: %u 0x%02x 0x%02x\n", ts, size, flags1, unknown1, header[4], header[5]);#endif size+=2; ph->object_version=0; ph->length=size; ph->stream_number=(flags1>>1)&1; ph->timestamp=ts; ph->reserved=0; ph->flags=0; /* TODO: determine keyframe flag and insert here? */ return size;}int real_get_rdt_chunk(rtsp_client_t *rtsp_session, rmff_pheader_t *ph, unsigned char **buffer) { int n; rmff_dump_pheader(ph, (char*)*buffer); n=rtsp_read_data(rtsp_session, (uint8_t*)(*buffer + 12), ph->length - 12); return (n <= 0) ? 0 : n+12;}//! maximum size of the rtsp description, must be < INT_MAX#define MAX_DESC_BUF (20 * 1024 * 1024)rmff_header_t *real_setup_and_get_header(rtsp_client_t *rtsp_session, int bandwidth) { char *description=NULL; char *session_id=NULL; rmff_header_t *h=NULL; char *challenge1 = NULL; char challenge2[64]; char checksum[34]; char *subscribe=NULL; char *buf=(char*)malloc(sizeof(char)*256); char *mrl=rtsp_get_mrl(rtsp_session); unsigned int size; int status; /* get challenge */ challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1")); lprintf("Challenge1: %s\n", challenge1); /* request stream description */ rtsp_schedule_field(rtsp_session, "Accept: application/sdp"); sprintf(buf, "Bandwidth: %u", bandwidth); rtsp_schedule_field(rtsp_session, buf); rtsp_schedule_field(rtsp_session, "GUID: 00000000-0000-0000-0000-000000000000"); rtsp_schedule_field(rtsp_session, "RegionData: 0"); rtsp_schedule_field(rtsp_session, "ClientID: Linux_2.4_6.0.9.1235_play32_RN01_EN_586"); rtsp_schedule_field(rtsp_session, "SupportsMaximumASMBandwidth: 1"); rtsp_schedule_field(rtsp_session, "Language: en-US"); rtsp_schedule_field(rtsp_session, "Require: com.real.retain-entity-for-setup"); status=rtsp_request_describe(rtsp_session,NULL); if ( status<200 || status>299 ) { char *alert=rtsp_search_answers(rtsp_session,"Alert"); if (alert) { lprintf("real: got message from server:\n%s\n", alert); } rtsp_send_ok( rtsp_session ); free( challenge1 ); free( alert ); free( buf ); return NULL; } /* receive description */ size=0; if (!rtsp_search_answers(rtsp_session,"Content-length")) lprintf("real: got no Content-length!\n"); else size=atoi(rtsp_search_answers(rtsp_session,"Content-length")); if (size > MAX_DESC_BUF) { printf("real: Content-length for description too big (> %uMB)!\n", MAX_DESC_BUF/(1024*1024) ); goto error; } if (!rtsp_search_answers(rtsp_session,"ETag")) lprintf("real: got no ETag!\n"); else session_id=strdup(rtsp_search_answers(rtsp_session,"ETag")); lprintf("Stream description size: %i\n", size); description = (char*)malloc(sizeof(char)*(size+1)); if( !description ) goto error; if( rtsp_read_data(rtsp_session, (uint8_t*)description, size) <= 0) goto error; description[size]=0; //fprintf(stderr, "%s", description); /* parse sdp (sdpplin) and create a header and a subscribe string */ subscribe = (char *) malloc(sizeof(char)*256); if( !subscribe ) goto error; strcpy(subscribe, "Subscribe: "); h=real_parse_sdp(description, &subscribe, bandwidth); if (!h) goto error; rmff_fix_header(h);#if 0 fprintf("Title: %s\nCopyright: %s\nAuthor: %s\nStreams: %i\n", h->cont->title, h->cont->copyright, h->cont->author, h->prop->num_streams);#endif /* setup our streams */ real_calc_response_and_checksum (challenge2, checksum, challenge1); buf = realloc(buf, strlen(challenge2) + strlen(checksum) + 32); sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum); rtsp_schedule_field(rtsp_session, buf); buf = realloc(buf, strlen(session_id) + 32); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); buf = realloc(buf, strlen(mrl) + 32); sprintf(buf, "%s/streamid=0", mrl); rtsp_request_setup(rtsp_session,buf); if (h->prop->num_streams > 1) { rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); buf = realloc(buf, strlen(session_id) + 32); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); buf = realloc(buf, strlen(mrl) + 32); sprintf(buf, "%s/streamid=1", mrl); rtsp_request_setup(rtsp_session,buf); } /* set stream parameter (bandwidth) with our subscribe string */ rtsp_schedule_field(rtsp_session, subscribe); rtsp_request_setparameter(rtsp_session,NULL); /* and finally send a play request */ rtsp_schedule_field(rtsp_session, "Range: npt=0-"); rtsp_request_play(rtsp_session,NULL); free( challenge1 ); free( session_id ); free( description ); free( subscribe ); free( buf ); return h;error: if( h ) rmff_free_header( h ); free( challenge1 ); free( session_id ); free( description ); free( subscribe ); free( buf ); return NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -