📄 real.c
字号:
mp_msg(MSGT_STREAM, MSGL_WARN, "realrtsp: rdt chunk not recognized: got 0x%02x\n", header[0]); return 0; } /* header[1] is channel, normally 0, ignored */ size=(header[2]<<8)+header[3]; flags1=header[4]; if ((flags1!=0x40)&&(flags1!=0x42)&&(flags1!=0x41)) {#ifdef LOG printf("got flags1: 0x%02x\n",flags1);#endif if(header[6] == 0x06) { // eof packet rtsp_read_data(rtsp_session, header, 7); // Skip the rest of the eof packet /* Some files have short auxiliary streams, we must ignore eof packets * for these streams to avoid premature eof. * Now the code declares eof only if the stream with id == 0 gets eof * (old code was: eof on the first eof packet received). */ if(flags1 & 0x7c) // ignore eof for streams with id != 0 return 0; mp_msg(MSGT_STREAM, MSGL_INFO, "realrtsp: Stream EOF detected\n"); return -1; } 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;#ifdef LOG printf("ignoring bytes:\n"); hexdump(header, 8);#endif n=rtsp_read_data(rtsp_session, header+4, 4); if (n<4) return 0; flags1=header[4]; size-=9; } flags2=header[7]; // header[5..6] == frame number in stream unknown1=(header[5]<<16)+(header[6]<<8)+(header[7]); n=rtsp_read_data(rtsp_session, header, 6); if (n<6) return 0; ts=AV_RB32(header); #ifdef LOG printf("ts: %u, size: %u, flags: 0x%02x, unknown values: 0x%06x 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)&0x1f; ph.timestamp=ts; ph.reserved=0; if ((flags2&1) == 0 && (prev_ts != ts || prev_stream_number != ph.stream_number)) { prev_ts = ts; prev_stream_number = ph.stream_number; ph.flags=2; } else ph.flags=0; *buffer = xbuffer_ensure_size(*buffer, 12+size); if(rdt_rawdata) { n=rtsp_read_data(rtsp_session, *buffer, size-12); return (n <= 0) ? 0 : n; } rmff_dump_pheader(&ph, *buffer); size-=12; n=rtsp_read_data(rtsp_session, (*buffer)+12, size); return (n <= 0) ? 0 : n+12;}static int convert_timestamp(char *str, int *sec, int *msec) { int hh, mm, ss, ms = 0; // Timestamp may be optionally quoted with ", skip it // Since the url is escaped when we get here, we skip the string "%22" if (!strncmp(str, "%22", 3)) str += 3; if (sscanf(str, "%d:%d:%d.%d", &hh, &mm, &ss, &ms) < 3) { hh = 0; if (sscanf(str, "%d:%d.%d", &mm, &ss, &ms) < 2) { mm = 0; if (sscanf(str, "%d.%d", &ss, &ms) < 1) { ss = 0; ms = 0; } } } if (sec) *sec = hh * 3600 + mm * 60 + ss; if (msec) *msec = ms; return 1;}//! 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_t *rtsp_session, uint32_t bandwidth, char *username, char *password) { char *description=NULL; char *session_id=NULL; rmff_header_t *h; char *challenge1; char challenge2[64]; char checksum[34]; char *subscribe; char *buf = xbuffer_init(256); char *mrl=rtsp_get_mrl(rtsp_session); unsigned int size; int status; uint32_t maxbandwidth = bandwidth; char* authfield = NULL; int i; /* get challenge */ challenge1=strdup(rtsp_search_answers(rtsp_session,"RealChallenge1"));#ifdef LOG printf("real: Challenge1: %s\n", challenge1);#endif /* set a reasonable default to get the best stream, unless bandwidth given */ if (!bandwidth) bandwidth = 10485800; /* request stream description */rtsp_send_describe: 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"); if(authfield) rtsp_schedule_field(rtsp_session, authfield); status=rtsp_request_describe(rtsp_session,NULL); if (status == 401) { int authlen, b64_authlen; char *authreq; char* authstr = NULL; if (authfield) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: authorization failed, check your credentials\n"); goto autherr; } if (!(authreq = rtsp_search_answers(rtsp_session,"WWW-Authenticate"))) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: 401 but no auth request, aborting\n"); goto autherr; } if (!username) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: auth required but no username supplied\n"); goto autherr; } if (!strstr(authreq, "Basic")) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: authenticator not supported (%s)\n", authreq); goto autherr; } authlen = strlen(username) + (password ? strlen(password) : 0) + 2; authstr = malloc(authlen); sprintf(authstr, "%s:%s", username, password ? password : ""); authfield = malloc(authlen*2+22); strcpy(authfield, "Authorization: Basic "); b64_authlen = base64_encode(authstr, authlen, authfield+21, authlen*2); free(authstr); if (b64_authlen < 0) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: base64 output overflow, this should never happen\n"); goto autherr; } authfield[b64_authlen+21] = 0; goto rtsp_send_describe; }autherr: if (authfield) free(authfield); if ( status<200 || status>299 ) { char *alert=rtsp_search_answers(rtsp_session,"Alert"); if (alert) { mp_msg(MSGT_STREAM, MSGL_WARN, "realrtsp: got message from server:\n%s\n", alert); } rtsp_send_ok(rtsp_session); buf = xbuffer_free(buf); return NULL; } /* receive description */ size=0; if (!rtsp_search_answers(rtsp_session,"Content-length")) mp_msg(MSGT_STREAM, MSGL_WARN, "real: got no Content-length!\n"); else size=atoi(rtsp_search_answers(rtsp_session,"Content-length")); // as size is unsigned this also catches the case (size < 0) if (size > MAX_DESC_BUF) { mp_msg(MSGT_STREAM, MSGL_ERR, "realrtsp: Content-length for description too big (> %uMB)!\n", MAX_DESC_BUF/(1024*1024) ); xbuffer_free(buf); return NULL; } if (!rtsp_search_answers(rtsp_session,"ETag")) mp_msg(MSGT_STREAM, MSGL_WARN, "realrtsp: got no ETag!\n"); else session_id=strdup(rtsp_search_answers(rtsp_session,"ETag")); #ifdef LOG printf("real: Stream description size: %u\n", size);#endif description=malloc(size+1); if( rtsp_read_data(rtsp_session, description, size) <= 0) { buf = xbuffer_free(buf); return NULL; } description[size]=0; /* parse sdp (sdpplin) and create a header and a subscribe string */ subscribe = xbuffer_init(256); strcpy(subscribe, "Subscribe: "); h=real_parse_sdp(description, &subscribe, bandwidth); if (!h) { subscribe = xbuffer_free(subscribe); buf = xbuffer_free(buf); return NULL; } rmff_fix_header(h);#ifdef LOG printf("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 = xbuffer_ensure_size(buf, strlen(challenge2) + strlen(checksum) + 32); sprintf(buf, "RealChallenge2: %s, sd=%s", challenge2, checksum); rtsp_schedule_field(rtsp_session, buf); buf = xbuffer_ensure_size(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 = xbuffer_ensure_size(buf, strlen(mrl) + 32); sprintf(buf, "%s/streamid=0", mrl); rtsp_request_setup(rtsp_session,buf,NULL); /* Do setup for all the other streams we subscribed to */ for (i = 1; i < h->prop->num_streams; i++) { rtsp_schedule_field(rtsp_session, "Transport: x-pn-tng/tcp;mode=play,rtp/avp/tcp;unicast;mode=play"); buf = xbuffer_ensure_size(buf, strlen(session_id) + 32); sprintf(buf, "If-Match: %s", session_id); rtsp_schedule_field(rtsp_session, buf); buf = xbuffer_ensure_size(buf, strlen(mrl) + 32); sprintf(buf, "%s/streamid=%d", mrl, i); rtsp_request_setup(rtsp_session,buf,NULL); } /* set stream parameter (bandwidth) with our subscribe string */ rtsp_schedule_field(rtsp_session, subscribe); rtsp_request_setparameter(rtsp_session,NULL); /* set delivery bandwidth */ if (maxbandwidth) { sprintf(buf, "SetDeliveryBandwidth: Bandwidth=%u;BackOff=0", maxbandwidth); rtsp_schedule_field(rtsp_session, buf); rtsp_request_setparameter(rtsp_session,NULL); } { int s_ss = 0, s_ms = 0, e_ss = 0, e_ms = 0; char *str; if ((str = rtsp_get_param(rtsp_session, "start"))) { convert_timestamp(str, &s_ss, &s_ms); free(str); } if ((str = rtsp_get_param(rtsp_session, "end"))) { convert_timestamp(str, &e_ss, &e_ms); free(str); } str = buf + sprintf(buf, s_ms ? "%s%d.%d-" : "%s%d-", "Range: npt=", s_ss, s_ms); if (e_ss || e_ms) sprintf(str, e_ms ? "%d.%d" : "%d", e_ss, e_ms); } rtsp_schedule_field(rtsp_session, buf); /* and finally send a play request */ rtsp_request_play(rtsp_session,NULL); subscribe = xbuffer_free(subscribe); buf = xbuffer_free(buf); return h;}struct real_rtsp_session_t *init_real_rtsp_session (void){ struct real_rtsp_session_t *real_rtsp_session = NULL; real_rtsp_session = malloc (sizeof (struct real_rtsp_session_t)); real_rtsp_session->recv = xbuffer_init (BUF_SIZE); real_rtsp_session->rdteof = 0; real_rtsp_session->rdt_rawdata = 0; return real_rtsp_session;}voidfree_real_rtsp_session (struct real_rtsp_session_t* real_session){ if (!real_session) return; xbuffer_free (real_session->recv); free (real_session);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -