static rmff_header_t *real_parse_sdp(char *data, char **stream_rules, uint32_t bandwidth) {

  sdpplin_t *desc;
  rmff_header_t *header;
  char *buf;
  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 = xbuffer_init(2048);
  header=calloc(1,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);
  header->streams=calloc(1,sizeof(rmff_mdpr_t*)*(desc->stream_count+1));
#ifdef LOG
    printf("number of streams: %u\n", desc->stream_count);
#endif

  for (i=0; i<desc->stream_count; i++) {

    int j=0;
    int n;
    char b[64];
    int rulematches[MAX_RULEMATCHES];

    if (!desc->stream[i])
      continue;
#ifdef LOG
    printf("calling asmrp_match with:\n%s\n%u\n", desc->stream[i]->asm_rule_book, bandwidth);
#endif
    n=asmrp_match(desc->stream[i]->asm_rule_book, bandwidth, rulematches);
    for (j=0; j<n; j++) {
#ifdef LOG
      printf("asmrp rule match: %u for stream %u\n", rulematches[j], desc->stream[i]->stream_id);
#endif
      sprintf(b,"stream=%u;rule=%u,", desc->stream[i]->stream_id, rulematches[j]);
      *stream_rules = xbuffer_strcat(*stream_rules, b);
    }

    if (!desc->stream[i]->mlti_data) {
	len = 0;
	buf = xbuffer_free(buf);
    } 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);

    duration=FFMAX(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=FFMAX(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);

  rmff_fix_header(header);
  buf = xbuffer_free(buf);
  sdpplin_free(desc);

  return header;
}
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 = NULL;
  char *challenge1 = NULL;
  char challenge2[41];
  char checksum[9];
  char *subscribe = NULL;
  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=rtsp_search_answers(rtsp_session,"RealChallenge1");
  if (!challenge1)
      goto out;
  challenge1=strdup(challenge1);
#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);
    goto out;
  }

  /* 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) );
    goto out;
  }

  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) {
    goto out;
  }
  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) {
    goto out;
  }
  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);

out:
  subscribe = xbuffer_free(subscribe);
  buf = xbuffer_free(buf);
  free(description);
  free(session_id);
  free(challenge1);
  return h;
}
Esempio n. 3
0
/*
 * parse sdp(stream description) lines.
 * 
 * subscribe is "Subscribe: " which is send with SET_PARAMETER request.
 *
 */
struct rmff_header_t *real_parse_sdp(char *data,char **subscribe,int bw)
{
  
    struct sdpreal_t *desc;
    struct list_h *p;
    struct rmff_header_t *rmff_header;
    uint8_t *buf;
    int *matched; /* array of matched rules. malloced in find_asmrule_match */
    int matched_rules;
    int i,j;
    int mlti_data_len;
  
    int subscribe_len = BUFSIZE_1K;
    char subbuf[32];
  
    int duration =0;
    int max_bit_rate = 0;
    int avg_bit_rate = 0;
    int max_packet_size = 0;
    int avg_packet_size = 0;

    desc = sdpreal_parse(data);
  
    rmff_header = new_rmff_header_t();
    rmff_header->fileheader = new_rmff_fileheader(4 + desc->stream_count);
    rmff_header->cont = new_rmff_cont(desc->title,desc->author,
				      desc->copyright,desc->abstract);
    rmff_header->data = new_rmff_dataheader(0,0);
    rmff_header->streams =
	(rmff_mdpr_t**)xmalloc(sizeof(struct rmff_mdpr_t*) * (desc->stream_count + 1));
    display(MSDL_VER,"number of streams: %u\n",desc->stream_count);
  
    *subscribe = (char *)xmalloc(subscribe_len);
    strcpy(*subscribe,"Subscribe: ");
  
    for(i = 0,p = desc->streams; i < desc->stream_count; i++,p = p->next) {
    
	struct sdpreal_stream_t *stream = (sdpreal_stream_t *)p->p;
  
	/*  Subscribe: stream=0;rule=16,stream=0;rule=17 */
    
	matched_rules = find_asmrule_match(stream->asm_rule_book,
					   &matched,bw);
	if((strlen(*subscribe) + 32 * matched_rules) > subscribe_len) {
	    /* subscribe should be longer */
	    subscribe_len = (subscribe_len * 2 >
			     strlen(*subscribe) + 32 * matched_rules) ?
		subscribe_len * 2 : strlen(*subscribe) + 32 * matched_rules;
	    *subscribe = (char *)xrealloc(*subscribe,subscribe_len);
	}
    
	for(j = 0; j < matched_rules ; j++) {
	    snprintf(subbuf,sizeof(subbuf),"stream=%u;rule=%u,",i,matched[j]);
	    strcat(*subscribe,subbuf);
	}
    
	buf = NULL;
	if(!stream->mlti_data) {
	    mlti_data_len = 0;
	}
	else {
	    /* buf is malloc()ed inside select_mlti_data */
	    mlti_data_len = select_mlti_data(stream->mlti_data,
					     stream->mlti_data_size,
					     matched[0],&buf);
	}
    
	rmff_header->streams[i] =
	    new_rmff_mdpr(stream->stream_id,
			  stream->max_bit_rate,
			  stream->avg_bit_rate,
			  stream->max_packet_size,
			  stream->avg_packet_size,
			  stream->start_time,
			  stream->preroll,
			  stream->duration,
			  stream->stream_name,
			  stream->mime_type,
			  mlti_data_len,
			  buf);
    
	duration = (duration > stream->duration) ? 
	    duration : stream->duration;
	max_bit_rate += stream->max_bit_rate;
	avg_bit_rate += stream->avg_bit_rate;
	max_packet_size = (max_packet_size > stream->max_packet_size) ?
	    max_packet_size : stream->max_packet_size;
    
	if(avg_packet_size) {
	    avg_packet_size = (avg_packet_size + stream->avg_packet_size) / 2;
	}
	else {
	    avg_packet_size = stream->avg_packet_size;
	}
    
	if(matched) {
	    free(matched);
	    matched = NULL;
	}
	if(buf) {
	    free(buf);
	    buf = NULL;
	}
    
    }
  
    if((*subscribe)[strlen(*subscribe) -1 ] == ',') {
	(*subscribe)[strlen(*subscribe) -1 ] = '\0'; /* delete last comma */
    }
  
    rmff_header->prop =
	new_rmff_prop(max_bit_rate,
		      avg_bit_rate,
		      max_packet_size,
		      avg_packet_size,
		      0,
		      duration,
		      0,0,0,
		      desc->stream_count,
		      desc->flags);

    rmff_fix_header(rmff_header);
  
    free_sdpreal_t(desc);

    rmff_print_header(rmff_header);
  
    return rmff_header;
}