Example #1
0
/*
 * get file property.
 * return value        packet size  ... success
 *                              -1  ... error
 */
int asf_get_file_property(const uint8_t *header,int asf_header_size,
			  struct asf_file_header_t *fileh)
{
    int pos = 0;
    int packet_size = 0;
  
    /*
      examine file properties
    */
    pos = find_asf_guid(header,0,asf_file_header_guid,asf_header_size);
    
    if(pos < 0) {
	goto failed;
    }
    
    if((pos + sizeof(struct asf_file_header_t )) > asf_header_size) {/* 2big */
	goto failed;
    }
    
    memcpy((uint8_t *)fileh,header + pos,sizeof(struct asf_file_header_t));
    
    /* little endian */
    fileh->file_size       = le2me_64(fileh->file_size);
    fileh->creation_time   = le2me_64(fileh->creation_time);
    fileh->num_packets     = le2me_64(fileh->num_packets);
    fileh->play_duration   = le2me_64(fileh->play_duration);
    fileh->send_duration   = le2me_64(fileh->send_duration);
    fileh->preroll         = le2me_64(fileh->preroll);
    fileh->flags           = le2me_32(fileh->flags);
    fileh->min_packet_size = le2me_32(fileh->min_packet_size);
    fileh->max_packet_size = le2me_32(fileh->max_packet_size);
    fileh->max_bitrate     = le2me_32(fileh->max_bitrate);
    
    display(MSDL_VER,"file size = %lld\n",fileh->file_size);
    display(MSDL_VER,"play_duration = %d\n",
	    fileh->play_duration/10000000);
    display(MSDL_VER,"send_duration = %d\n",
	    fileh->send_duration/10000000);
    display(MSDL_VER,"# of packets = %d\n",
	    fileh->num_packets);
    display(MSDL_VER,"flags = %x\n",
	    fileh->flags);
	
    packet_size = fileh->max_packet_size;

    display(MSDL_VER,"packet_size = %d\n",
	    fileh->max_packet_size);
    display(MSDL_VER,"min_packsize = %d\n",
	    fileh->min_packet_size);
    
    return packet_size;
    
  failed:
    return -1;
}
Example #2
0
static int get_meta(char *buf, int buf_len, int this_stream_num,
    float* asp_ratio)
{
  int pos = 0;
  uint16_t records_count;
  uint16_t x = 0, y = 0;

  if ((pos = find_asf_guid(buf, asf_metadata_header, pos, buf_len)) < 0)
    return 0;

  CHECKDEC(buf_len, pos);
  buf += pos;
  CHECKDEC(buf_len, 2);
  records_count = AV_RL16(buf);
  buf += 2;

  while (records_count--) {
    ASF_meta_record_t record_entry;
    char* name;

    if (!(buf = read_meta_record(&record_entry, buf, &buf_len)))
        return 0;
    /* reserved, must be zero */
    if (record_entry.lang_list_index)
      continue;
    /* match stream number: 0 to match all */
    if (record_entry.stream_num && record_entry.stream_num != this_stream_num)
      continue;
    if (!(name = get_ucs2str(record_entry.name, record_entry.name_length))) {
      mp_msg(MSGT_HEADER, MSGL_ERR, MSGTR_MemAllocFailed);
      continue;
    }
    if (strcmp(name, "AspectRatioX") == 0)
      x = AV_RL16(record_entry.data);
    else if (strcmp(name, "AspectRatioY") == 0)
      y = AV_RL16(record_entry.data);
    free(name);
  }
  if (x && y) {
    *asp_ratio = (float)x / (float)y;
    return 1;
  }
  return 0;
}
Example #3
0
static int is_drm(char* buf, int buf_len)
{
  uint32_t data_len, type_len, key_len, url_len;
  int pos = find_asf_guid(buf, asf_content_encryption, 0, buf_len);

  if (pos < 0)
    return 0;

  CHECKDEC(buf_len, pos + 4);
  buf += pos;
  data_len = AV_RL32(buf);
  buf += 4;
  CHECKDEC(buf_len, data_len);
  buf += data_len;
  type_len = AV_RL32(buf);
  if (type_len < 4)
    return 0;
  CHECKDEC(buf_len, 4 + type_len + 4);
  buf += 4;

  if (buf[0] != 'D' || buf[1] != 'R' || buf[2] != 'M' || buf[3] != '\0')
    return 0;

  buf += type_len;
  key_len = AV_RL32(buf);
  CHECKDEC(buf_len, key_len + 4);
  buf += 4;

  buf[key_len - 1] = '\0';
  mp_msg(MSGT_HEADER, MSGL_V, "DRM Key ID: %s\n", buf);

  buf += key_len;
  url_len = AV_RL32(buf);
  CHECKDEC(buf_len, url_len);
  buf += 4;

  buf[url_len - 1] = '\0';
  mp_msg(MSGT_HEADER, MSGL_INFO, MSGTR_MPDEMUX_ASFHDR_DRMLicenseURL, buf);
  return 1;
}
Example #4
0
/*
 * choose best audio and video streams, below bw.
 * 'header' is an asf header, and 'asf_header_size' is its size.
 * the result will be in 'streams'
 *             return value:   1  ... success
 *                            -1  ... failed
 */
int asf_choose_best_streams(const uint8_t *header, int asf_header_size,
			    int bw, struct asf_streams_t *streams)
{

    int i = 0,pos = 0,start = 0;
    int *v_rates = NULL, *a_rates = NULL;
    int v_rate = 0, a_rate = 0, v_idx = -1, a_idx = -1;
  
    /*
      header is entire ASF header, including very first asf_header_t.
    */
    pos = sizeof(struct asf_header_t);
    start = pos;
  
    /*
      choose best (fastest) streams
    */
  
    while((pos = find_asf_guid(header,pos,asf_stream_header_guid,asf_header_size)) >= 0) {
	struct asf_stream_header_t *streamh = 
	    (struct asf_stream_header_t *)(header + pos);

	pos += sizeof(struct asf_stream_header_t);
	if(pos > asf_header_size)  /* error */
	    return -1;
    
    
	/* get ASF GUID PREFIX (first 4 byte of GUID) */
	switch(get32_le(streamh->type)) {
	    
	case ASF_AUDIO_STREAM: /* audio stream */
	    display(MSDL_VER,"audio stream detected!!!!\n");
	    if(streams->audio_streams == NULL) { /* no audio stream registerd yet */
		streams->audio_streams = (int *)xmalloc(sizeof(int));
		streams->n_audio = 1;
	    }
	    else { /* more audio streams.!! */
		streams->n_audio++;
		streams->audio_streams = 
		    (int *)xrealloc(streams->audio_streams,
				    streams->n_audio * sizeof(int));
	    }
	    streams->audio_streams[streams->n_audio - 1] =
		le2me_16(streamh->stream_no);
	    break;
      
	case ASF_VIDEO_STREAM: /* video streams */
	    display(MSDL_VER,"video stream detected!!!!\n");
	    if(streams->video_streams == NULL) { /* no video stream registerd yet */
		streams->video_streams = (int *)xmalloc(sizeof(int));
		streams->n_video = 1;
	    }
	    else { /* more video streams.!! */
		streams->n_video++;
		streams->video_streams = 
		    (int *)xrealloc(streams->video_streams,
				    streams->n_video * sizeof(int));
	    }
	    streams->video_streams[streams->n_video - 1] =
		le2me_16(streamh->stream_no);
	    break;
      
	case ASF_COMMAND_MEDIA_STREAM: /* Command media stream... whatever*/
	    display(MSDL_VER,"Command media stream detected, but ignore this.\n");
	    break;
      
	case ASF_FILE_TRANSFER_MEDIA_STREAM: /* File transfer media stream... 
						I don't know what the heck this is.*/
	    display(MSDL_VER,"File transfer stream detected, but ignore this.\n");
	    break;
      
	}
    }

    a_rates = (int *)xmalloc(streams->n_audio * sizeof(int));
    v_rates = (int *)xmalloc(streams->n_video * sizeof(int));

  
    pos = find_asf_guid(header,start,asf_stream_group_guid,asf_header_size);
    if(pos >= 0) {
	/* stream bitrate proterties object */

	int stream_count = 0;
	uint8_t *ptr = (uint8_t *)header + pos;
	
	display(MSDL_VER,"stream bitrate properties object\n");
    
	stream_count = get16_le(ptr); /* little endian. */
	ptr += sizeof(uint16_t);
	if(ptr > header + asf_header_size) goto failed;
	display(MSDL_VER,"stream count = [0x%x] [%u]\n",stream_count,stream_count);
	display(MSDL_VER,"audio streams: %d, video streams: %d\n",
		streams->n_audio,streams->n_video);

	for(i = 0; i < stream_count; i++) {
	    uint32_t rate = 0;
	    int id = 0;
	    int j = 0;
      
	    id = get16_le(ptr);
	    ptr += sizeof(uint16_t);
	    if(ptr > header + asf_header_size) goto failed;
	    rate = get32_le(ptr);
	    ptr += sizeof(uint32_t);
	    if(ptr > header + asf_header_size) goto failed;
      
	    display(MSDL_VER,
		    "stream_id   = [0x%x] [%u]\n"
		    "max bitrate = [0x%x] [%u]\n",
		    id,id,rate,rate);
      
	    for(j = 0; j < streams->n_audio; j++) {
		if(id == streams->audio_streams[j]) {
		    display(MSDL_VER,"is audio stream\n");
		    a_rates[j] = rate;
		    break;
		}
	    }
	    for(j = 0; j < streams->n_video; j++) {
		if(id == streams->video_streams[j]) {
		    display(MSDL_VER,"is video stream\n");
		    v_rates[j] = rate;
		    break;
		}
	    }
	}
    }

    /* just to make sure bw is not Zero! */
    if(bw == 0) {
	bw = INT_MAX_BANDWIDTH;
    }

    if(streams->n_audio) {
	/* find lowest-bitrate audio stream */
	a_rate = a_rates[0];
	a_idx = 0;
	for(i = 0; i < streams->n_audio; i++) {
	    if(a_rates[i] < a_rate) {
		a_rate = a_rates[i];
		a_idx = i;
	    }
	}
	if(max_idx(streams->n_video,v_rates,bw - a_rate) < 0) {
	    /* both audio and video are not possible, try video only next */
	    a_idx = -1;
	    a_rate = 0;
	}
    }
  
    /* find best video stream */
    v_idx = max_idx(streams->n_video,v_rates,bw - a_rate);
    if(v_idx >= 0) {
	v_rate = v_rates[v_idx];
    }
  
    /* find best auido stream */
    a_idx = max_idx(streams->n_audio,a_rates,bw - v_rate);

    free(v_rates);
    v_rates = NULL;
    free(a_rates);
    a_rates = NULL;

    if(a_idx < 0 && v_idx < 0) {
	display(MSDL_ERR,"bandwidth too low ... cannot get streams.");
	return -1;
    }
  
  
    if(a_idx >= 0) {
	streams->audio_id = streams->audio_streams[a_idx];
    }
    else if(streams->n_audio) {
	display(MSDL_ERR,"Bandwidth too too small so deselected audio....sad.\n");
    }
  
    if(v_idx >= 0) {
	streams->video_id = streams->video_streams[v_idx];
    }
    else if(streams->n_video) {
	display(MSDL_ERR,"Bandwidth too too small so deselected video....sad.\n");
    }
  
  
    return 1;

  failed:
    free(v_rates);
    free(a_rates);
    return -1;

}
Example #5
0
int read_asf_header(demuxer_t *demuxer,struct asf_priv* asf){
  int hdr_len = asf->header.objh.size - sizeof(asf->header);
  int hdr_skip = 0;
  char *hdr = NULL;
  char guid_buffer[16];
  int pos, start = stream_tell(demuxer->stream);
  uint32_t* streams = NULL;
  int audio_streams=0;
  int video_streams=0;
  uint16_t stream_count=0;
  int best_video = -1;
  int best_audio = -1;
  uint64_t data_len;
  ASF_stream_header_t *streamh;
  uint8_t *buffer;
  int audio_pos=0;

  if(hdr_len < 0) {
    mp_msg(MSGT_HEADER, MSGL_FATAL, "Header size is too small.\n");
    return 0;
  }

  if (hdr_len > 1024 * 1024) {
    mp_msg(MSGT_HEADER, MSGL_ERR, MSGTR_MPDEMUX_ASFHDR_HeaderSizeOver1MB,
			hdr_len);
    hdr_skip = hdr_len - 1024 * 1024;
    hdr_len = 1024 * 1024;
  }
  hdr = malloc(hdr_len);
  if (!hdr) {
    mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_HeaderMallocFailed,
            hdr_len);
    return 0;
  }
  stream_read(demuxer->stream, hdr, hdr_len);
  if (hdr_skip)
    stream_skip(demuxer->stream, hdr_skip);
  if (stream_eof(demuxer->stream)) {
    mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_EOFWhileReadingHeader);
    goto err_out;
  }

  if (is_drm(hdr, hdr_len))
    mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_DRMProtected);

  if ((pos = find_asf_guid(hdr, asf_ext_stream_audio, 0, hdr_len)) >= 0)
  {
    // Special case: found GUID for dvr-ms audio.
    // Now skip back to associated stream header.
    int sh_pos=0;

    sh_pos = find_backwards_asf_guid(hdr, asf_stream_header_guid, pos);

    if (sh_pos > 0) {
      sh_audio_t *sh_audio;

       mp_msg(MSGT_HEADER, MSGL_V, "read_asf_header found dvr-ms audio stream header pos=%d\n", sh_pos);
      // found audio stream header - following code reads header and
      // initializes audio stream.
      audio_pos = pos - 16 - 8;
      streamh = (ASF_stream_header_t *)&hdr[sh_pos];
      le2me_ASF_stream_header_t(streamh);
      audio_pos += 64; //16+16+4+4+4+16+4;
      buffer = &hdr[audio_pos];
      sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F, NULL);
      sh_audio->needs_parsing = 1;
      mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "asfheader", streamh->stream_no & 0x7F);
      ++audio_streams;
      if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &audio_pos, &buffer, hdr, hdr_len))
        goto len_err_out;
      if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 0))
        goto len_err_out;
    }
  }
  // find stream headers
  // only reset pos if we didnt find dvr_ms audio stream
  // if we did find it then we want to avoid reading its header twice
  if (audio_pos == 0)
    pos = 0;

  while ((pos = find_asf_guid(hdr, asf_stream_header_guid, pos, hdr_len)) >= 0)
  {
    streamh = (ASF_stream_header_t *)&hdr[pos];
    pos += sizeof(ASF_stream_header_t);
    if (pos > hdr_len) goto len_err_out;
    le2me_ASF_stream_header_t(streamh);
    mp_msg(MSGT_HEADER, MSGL_V, "stream type: %s\n",
            asf_chunk_type(streamh->type));
    mp_msg(MSGT_HEADER, MSGL_V, "stream concealment: %s\n",
            asf_chunk_type(streamh->concealment));
    mp_msg(MSGT_HEADER, MSGL_V, "type: %d bytes,  stream: %d bytes  ID: %d\n",
            (int)streamh->type_size, (int)streamh->stream_size,
            (int)streamh->stream_no);
    mp_msg(MSGT_HEADER, MSGL_V, "unk1: %lX  unk2: %X\n",
            (unsigned long)streamh->unk1, (unsigned int)streamh->unk2);
    mp_msg(MSGT_HEADER, MSGL_V, "FILEPOS=0x%X\n", pos + start);
    // type-specific data:
    buffer = &hdr[pos];
    pos += streamh->type_size;
    if (pos > hdr_len) goto len_err_out;
    switch(ASF_LOAD_GUID_PREFIX(streamh->type)){
      case ASF_GUID_PREFIX_audio_stream: {
        sh_audio_t* sh_audio=new_sh_audio(demuxer,streamh->stream_no & 0x7F, NULL);
        mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_AudioID, "asfheader", streamh->stream_no & 0x7F);
        ++audio_streams;
        if (!asf_init_audio_stream(demuxer, asf, sh_audio, streamh, &pos, &buffer, hdr, hdr_len))
          goto len_err_out;
	//if(demuxer->audio->id==-1) demuxer->audio->id=streamh.stream_no & 0x7F;
        break;
        }
      case ASF_GUID_PREFIX_video_stream: {
        unsigned int len;
        float asp_ratio;
        sh_video_t* sh_video=new_sh_video(demuxer,streamh->stream_no & 0x7F);
        mp_msg(MSGT_DEMUX, MSGL_INFO, MSGTR_VideoID, "asfheader", streamh->stream_no & 0x7F);
        len=streamh->type_size-(4+4+1+2);
	++video_streams;
//        sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
        sh_video->bih=calloc((len<sizeof(*sh_video->bih))?sizeof(*sh_video->bih):len,1);
        memcpy(sh_video->bih,&buffer[4+4+1+2],len);
	le2me_BITMAPINFOHEADER(sh_video->bih);
	if (sh_video->bih->biSize > len && sh_video->bih->biSize > sizeof(*sh_video->bih))
		sh_video->bih->biSize = len;
        if (sh_video->bih->biCompression == mmioFOURCC('D', 'V', 'R', ' ')) {
          //mp_msg(MSGT_DEMUXER, MSGL_WARN, MSGTR_MPDEMUX_ASFHDR_DVRWantsLibavformat);
          //sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
          //sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
          asf->asf_frame_state=-1;
          asf->asf_frame_start_found=0;
          asf->asf_is_dvr_ms=1;
          asf->dvr_last_vid_pts=0.0;
        } else asf->asf_is_dvr_ms=0;
        if (!get_ext_stream_properties(hdr, hdr_len, streamh->stream_no, asf, 1))
            goto len_err_out;
        if (get_meta(hdr, hdr_len, streamh->stream_no, &asp_ratio)) {
          sh_video->aspect = asp_ratio * sh_video->bih->biWidth /
            sh_video->bih->biHeight;
        }
        sh_video->i_bps = asf->bps;

        if( mp_msg_test(MSGT_DEMUX,MSGL_V) ) print_video_header(sh_video->bih, MSGL_V);
        //asf_video_id=streamh.stream_no & 0x7F;
	//if(demuxer->video->id==-1) demuxer->video->id=streamh.stream_no & 0x7F;
        break;
        }
      }
      // stream-specific data:
      // stream_read(demuxer->stream,(char*) buffer,streamh.stream_size);
  }

  // find file header
  pos = find_asf_guid(hdr, asf_file_header_guid, 0, hdr_len);
  if (pos >= 0) {
      ASF_file_header_t *fileh = (ASF_file_header_t *)&hdr[pos];
      pos += sizeof(ASF_file_header_t);
      if (pos > hdr_len) goto len_err_out;
      le2me_ASF_file_header_t(fileh);
      mp_msg(MSGT_HEADER, MSGL_V, "ASF: packets: %d  flags: %d  "
              "max_packet_size: %d  min_packet_size: %d  max_bitrate: %d  "
              "preroll: %d\n",
              (int)fileh->num_packets, (int)fileh->flags,
              (int)fileh->min_packet_size, (int)fileh->max_packet_size,
              (int)fileh->max_bitrate, (int)fileh->preroll);
      asf->packetsize=fileh->max_packet_size;
      asf->packet=malloc(asf->packetsize); // !!!
      asf->packetrate=fileh->max_bitrate/8.0/(double)asf->packetsize;
      asf->movielength=(fileh->play_duration-10000*fileh->preroll)/10000000.0;
  }

  // find content header
  pos = find_asf_guid(hdr, asf_content_desc_guid, 0, hdr_len);
  if (pos >= 0) {
        ASF_content_description_t *contenth = (ASF_content_description_t *)&hdr[pos];
        char *string=NULL;
        uint16_t* wstring = NULL;
        uint16_t len;
        pos += sizeof(ASF_content_description_t);
        if (pos > hdr_len) goto len_err_out;
	le2me_ASF_content_description_t(contenth);
	mp_msg(MSGT_HEADER,MSGL_V,"\n");
        // extract the title
        if((len = contenth->title_size) != 0) {
          wstring = (uint16_t*)&hdr[pos];
          pos += len;
          if (pos > hdr_len) goto len_err_out;
          if ((string = get_ucs2str(wstring, len))) {
            mp_msg(MSGT_HEADER,MSGL_V," Title: %s\n", string);
            demux_info_add(demuxer, "title", string);
            free(string);
          }
        }
        // extract the author
        if((len = contenth->author_size) != 0) {
          wstring = (uint16_t*)&hdr[pos];
          pos += len;
          if (pos > hdr_len) goto len_err_out;
          if ((string = get_ucs2str(wstring, len))) {
            mp_msg(MSGT_HEADER,MSGL_V," Author: %s\n", string);
            demux_info_add(demuxer, "author", string);
            free(string);
          }
        }
        // extract the copyright
        if((len = contenth->copyright_size) != 0) {
          wstring = (uint16_t*)&hdr[pos];
          pos += len;
          if (pos > hdr_len) goto len_err_out;
          if ((string = get_ucs2str(wstring, len))) {
            mp_msg(MSGT_HEADER,MSGL_V," Copyright: %s\n", string);
            demux_info_add(demuxer, "copyright", string);
            free(string);
          }
        }
        // extract the comment
        if((len = contenth->comment_size) != 0) {
          wstring = (uint16_t*)&hdr[pos];
          pos += len;
          if (pos > hdr_len) goto len_err_out;
          if ((string = get_ucs2str(wstring, len))) {
            mp_msg(MSGT_HEADER,MSGL_V," Comment: %s\n", string);
            demux_info_add(demuxer, "comments", string);
            free(string);
          }
        }
        // extract the rating
        if((len = contenth->rating_size) != 0) {
          wstring = (uint16_t*)&hdr[pos];
          pos += len;
          if (pos > hdr_len) goto len_err_out;
          if ((string = get_ucs2str(wstring, len))) {
            mp_msg(MSGT_HEADER,MSGL_V," Rating: %s\n", string);
            free(string);
          }
        }
	mp_msg(MSGT_HEADER,MSGL_V,"\n");
  }

  // find content header
  pos = find_asf_guid(hdr, asf_stream_group_guid, 0, hdr_len);
  if (pos >= 0) {
        int max_streams = (hdr_len - pos - 2) / 6;
        uint16_t stream_id, i;
        uint32_t max_bitrate;
        char *ptr = &hdr[pos];
        mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == START ===\n");
        if(max_streams <= 0) goto len_err_out;
        stream_count = AV_RL16(ptr);
        ptr += sizeof(uint16_t);
        if(stream_count > max_streams) stream_count = max_streams;
        if(stream_count > 0)
              streams = malloc(2*stream_count*sizeof(uint32_t));
        mp_msg(MSGT_HEADER,MSGL_V," stream count=[0x%x][%u]\n", stream_count, stream_count );
        for( i=0 ; i<stream_count ; i++ ) {
          stream_id = AV_RL16(ptr);
          ptr += sizeof(uint16_t);
          max_bitrate = AV_RL32(ptr);
          ptr += sizeof(uint32_t);
          mp_msg(MSGT_HEADER,MSGL_V,"   stream id=[0x%x][%u]\n", stream_id, stream_id );
          mp_msg(MSGT_HEADER,MSGL_V,"   max bitrate=[0x%x][%u]\n", max_bitrate, max_bitrate );
          streams[2*i] = stream_id;
          streams[2*i+1] = max_bitrate;
        }
        mp_msg(MSGT_HEADER,MSGL_V,"============ ASF Stream group == END ===\n");
  }
  free(hdr);
  hdr = NULL;
  start = stream_tell(demuxer->stream); // start of first data chunk
  stream_read(demuxer->stream, guid_buffer, 16);
  if (memcmp(guid_buffer, asf_data_chunk_guid, 16) != 0) {
    mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_NoDataChunkAfterHeader);
    free(streams);
    streams = NULL;
    return 0;
  }
  // read length of chunk
  data_len = stream_read_qword_le(demuxer->stream);
  demuxer->movi_start = stream_tell(demuxer->stream) + 26;
  demuxer->movi_end = start + data_len;
  mp_msg(MSGT_HEADER, MSGL_V, "Found movie at 0x%X - 0x%X\n",
          (int)demuxer->movi_start, (int)demuxer->movi_end);

if(streams) {
  // stream selection is done in the network code, it shouldn't be done here
  // as the servers often do not care about what we requested.
#if 0
  uint32_t vr = 0, ar = 0,i;
#ifdef CONFIG_NETWORKING
  if( demuxer->stream->streaming_ctrl!=NULL ) {
	  if( demuxer->stream->streaming_ctrl->bandwidth!=0 && demuxer->stream->streaming_ctrl->data!=NULL ) {
		  best_audio = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->audio_id;
		  best_video = ((asf_http_streaming_ctrl_t*)demuxer->stream->streaming_ctrl->data)->video_id;
	  }
  } else
#endif
  for(i = 0; i < stream_count; i++) {
    uint32_t id = streams[2*i];
    uint32_t rate = streams[2*i+1];
    if(demuxer->v_streams[id] && rate > vr) {
      vr = rate;
      best_video = id;
    } else if(demuxer->a_streams[id] && rate > ar) {
      ar = rate;
      best_audio = id;
    }
  }
#endif
  free(streams);
  streams = NULL;
}

mp_msg(MSGT_HEADER,MSGL_V,"ASF: %d audio and %d video streams found\n",audio_streams,video_streams);
if(!audio_streams) demuxer->audio->id=-2;  // nosound
else if(best_audio > 0 && demuxer->audio->id == -1) demuxer->audio->id=best_audio;
if(!video_streams){
    if(!audio_streams){
	mp_msg(MSGT_HEADER,MSGL_ERR,MSGTR_MPDEMUX_ASFHDR_AudioVideoHeaderNotFound);
	return 0;
    }
    demuxer->video->id=-2; // audio-only
} else if (best_video > 0 && demuxer->video->id == -1) demuxer->video->id = best_video;

#if 0
if( mp_msg_test(MSGT_HEADER,MSGL_V) ){
    printf("ASF duration: %d\n",(int)fileh.duration);
    printf("ASF start pts: %d\n",(int)fileh.start_timestamp);
    printf("ASF end pts: %d\n",(int)fileh.end_timestamp);
}
#endif

return 1;

len_err_out:
  mp_msg(MSGT_HEADER, MSGL_FATAL, MSGTR_MPDEMUX_ASFHDR_InvalidLengthInASFHeader);
err_out:
  if (hdr) free(hdr);
  if (streams) free(streams);
  return 0;
}
Example #6
0
static int get_ext_stream_properties(char *buf, int buf_len, int stream_num, struct asf_priv* asf, int is_video)
{
  int pos=0;
  uint8_t *buffer = &buf[0];
  uint64_t avg_ft;
  unsigned bitrate;

  while ((pos = find_asf_guid(buf, asf_ext_stream_header, pos, buf_len)) >= 0) {
    int this_stream_num, stnamect, payct, i;
    int buf_max_index=pos+50;
    if (buf_max_index > buf_len) return 0;
    buffer = &buf[pos];

    // the following info is available
    // some of it may be useful but we're skipping it for now
    // starttime(8 bytes), endtime(8),
    // leak-datarate(4), bucket-datasize(4), init-bucket-fullness(4),
    // alt-leak-datarate(4), alt-bucket-datasize(4), alt-init-bucket-fullness(4),
    // max-object-size(4),
    // flags(4) (reliable,seekable,no_cleanpoints?,resend-live-cleanpoints, rest of bits reserved)

    buffer += 8+8;
    bitrate = AV_RL32(buffer);
    buffer += 8*4;
    this_stream_num=AV_RL16(buffer);buffer+=2;

    if (this_stream_num == stream_num) {
      buf_max_index+=14;
      if (buf_max_index > buf_len) return 0;
      buffer+=2; //skip stream-language-id-index
      avg_ft = AV_RL64(buffer); // provided in 100ns units
      buffer+=8;
      asf->bps = bitrate / 8;

      // after this are values for stream-name-count and
      // payload-extension-system-count
      // followed by associated info for each
      stnamect = AV_RL16(buffer);buffer+=2;
      payct = AV_RL16(buffer);buffer+=2;

      // need to read stream names if present in order
      // to get lengths - values are ignored for now
      for (i=0; i<stnamect; i++) {
        int stream_name_len;
        buf_max_index+=4;
        if (buf_max_index > buf_len) return 0;
        buffer+=2; //language_id_index
        stream_name_len = AV_RL16(buffer);buffer+=2;
        buffer+=stream_name_len; //stream_name
        buf_max_index+=stream_name_len;
        if (buf_max_index > buf_len) return 0;
      }

      if (is_video) {
        asf->vid_repdata_count = payct;
        asf->vid_repdata_sizes = malloc(payct*sizeof(int));
      } else {
        asf->aud_repdata_count = payct;
        asf->aud_repdata_sizes = malloc(payct*sizeof(int));
      }

      for (i=0; i<payct; i++) {
        int payload_len;
        buf_max_index+=22;
        if (buf_max_index > buf_len) return 0;
        // Each payload extension definition starts with a GUID.
        // In dvr-ms files one of these indicates the presence an
        // extension that contains pts values and this is always present
        // in the video and audio streams.
        // Another GUID indicates the presence of an extension
        // that contains useful video frame demuxing information.
        // Note that the extension data in each packet does not contain
        // these GUIDs and that this header section defines the order the data
        // will appear in.
        if (memcmp(buffer, asf_dvr_ms_timing_rep_data, 16) == 0) {
          if (is_video)
            asf->vid_ext_timing_index = i;
          else
            asf->aud_ext_timing_index = i;
        } else if (is_video && memcmp(buffer, asf_dvr_ms_vid_frame_rep_data, 16) == 0)
          asf->vid_ext_frame_index = i;
        buffer+=16;

        payload_len = AV_RL16(buffer);buffer+=2;

        if (is_video)
          asf->vid_repdata_sizes[i] = payload_len;
        else
          asf->aud_repdata_sizes[i] = payload_len;
        buffer+=4;//sys_len
      }

      return 1;
    }
  }
  return 1;
}
Example #7
0
static int asf_streaming_parse_header(int fd, streaming_ctrl_t* streaming_ctrl) {
  ASF_stream_chunck_t chunk;
  asf_http_streaming_ctrl_t* asf_ctrl = streaming_ctrl->data;
  char* buffer=NULL, *chunk_buffer=NULL;
  int i,r,size,pos = 0;
  int start;
  int buffer_size = 0;
  int chunk_size2read = 0;
  int bw = streaming_ctrl->bandwidth;
  int *v_rates = NULL, *a_rates = NULL;
  int v_rate = 0, a_rate = 0, a_idx = -1, v_idx = -1;

  if(asf_ctrl == NULL) return -1;

	// The ASF header can be in several network chunks. For example if the content description
	// is big, the ASF header will be split in 2 network chunk.
	// So we need to retrieve all the chunk before starting to parse the header.
  do {
	  if (asf_read_wrapper(fd, &chunk, sizeof(ASF_stream_chunck_t), streaming_ctrl) <= 0)
	    return -1;
	  // Endian handling of the stream chunk
	  le2me_ASF_stream_chunck_t(&chunk);
	  size = asf_streaming( &chunk, &r) - sizeof(ASF_stream_chunck_t);
	  if(r) mp_msg(MSGT_NETWORK,MSGL_WARN,MSGTR_MPDEMUX_ASF_WarnDropHeader);
	  if(size < 0){
	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrorParsingChunkHeader);
		return -1;
	  }
	  if (chunk.type != ASF_STREAMING_HEADER) {
	    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_NoHeaderAtFirstChunk);
	    return -1;
	  }

	  // audit: do not overflow buffer_size
	  if (size > SIZE_MAX - buffer_size) return -1;
	  buffer = malloc(size+buffer_size);
	  if(buffer == NULL) {
	    mp_msg(MSGT_NETWORK,MSGL_FATAL,MSGTR_MPDEMUX_ASF_BufferMallocFailed,size+buffer_size);
	    return -1;
	  }
	  if( chunk_buffer!=NULL ) {
	  	memcpy( buffer, chunk_buffer, buffer_size );
		free( chunk_buffer );
	  }
	  chunk_buffer = buffer;
	  buffer += buffer_size;
	  buffer_size += size;

	  if (asf_read_wrapper(fd, buffer, size, streaming_ctrl) <= 0)
	    return -1;

	  if( chunk_size2read==0 ) {
		ASF_header_t *asfh = (ASF_header_t *)buffer;
		if(size < (int)sizeof(ASF_header_t)) {
		    mp_msg(MSGT_NETWORK,MSGL_ERR,MSGTR_MPDEMUX_ASF_ErrChunk2Small);
		    return -1;
		} else mp_msg(MSGT_NETWORK,MSGL_DBG2,"Got chunk\n");
		chunk_size2read = AV_RL64(&asfh->objh.size);
		mp_msg(MSGT_NETWORK,MSGL_DBG2,"Size 2 read=%d\n", chunk_size2read);
	  }
  } while( buffer_size<chunk_size2read);
  buffer = chunk_buffer;
  size = buffer_size;

  start = sizeof(ASF_header_t);

  pos = find_asf_guid(buffer, asf_file_header_guid, start, size);
  if (pos >= 0) {
    ASF_file_header_t *fileh = (ASF_file_header_t *) &buffer[pos];
    pos += sizeof(ASF_file_header_t);
    if (pos > size) goto len_err_out;
/*
      if(fileh.packetsize != fileh.packetsize2) {
	printf("Error packetsize check don't match\n");
	return -1;
      }
*/
      asf_ctrl->packet_size = AV_RL32(&fileh->max_packet_size);
      // before playing.
      // preroll: time in ms to bufferize before playing
      streaming_ctrl->prebuffer_size = (unsigned int)(((double)fileh->preroll/1000.0)*((double)fileh->max_bitrate/8.0));
  }

  pos = start;
  while ((pos = find_asf_guid(buffer, asf_stream_header_guid, pos, size)) >= 0)
  {
    ASF_stream_header_t *streamh = (ASF_stream_header_t *)&buffer[pos];
    pos += sizeof(ASF_stream_header_t);
    if (pos > size) goto len_err_out;
      switch(ASF_LOAD_GUID_PREFIX(streamh->type)) {
      case 0xF8699E40 : // audio stream
	if(asf_ctrl->audio_streams == NULL){
	  asf_ctrl->audio_streams = malloc(sizeof(int));
	  asf_ctrl->n_audio = 1;
	} else {
	  asf_ctrl->n_audio++;
	  asf_ctrl->audio_streams = realloc(asf_ctrl->audio_streams,
						     asf_ctrl->n_audio*sizeof(int));
	}
	asf_ctrl->audio_streams[asf_ctrl->n_audio-1] = AV_RL16(&streamh->stream_no);
	break;
      case 0xBC19EFC0 : // video stream
	if(asf_ctrl->video_streams == NULL){
	  asf_ctrl->video_streams = malloc(sizeof(int));
	  asf_ctrl->n_video = 1;
	} else {
	  asf_ctrl->n_video++;
	  asf_ctrl->video_streams = realloc(asf_ctrl->video_streams,
						     asf_ctrl->n_video*sizeof(int));
	}
	asf_ctrl->video_streams[asf_ctrl->n_video-1] = AV_RL16(&streamh->stream_no);
	break;
      }
  }

  // always allocate to avoid lots of ifs later
  v_rates = calloc(asf_ctrl->n_video, sizeof(int));
  a_rates = calloc(asf_ctrl->n_audio, sizeof(int));

  pos = find_asf_guid(buffer, asf_stream_group_guid, start, size);
  if (pos >= 0) {
    // stream bitrate properties object
	int stream_count;
	char *ptr = &buffer[pos];
	char *end = &buffer[size];

	mp_msg(MSGT_NETWORK, MSGL_V, "Stream bitrate properties object\n");
		if (ptr + 2 > end) goto len_err_out;
		stream_count = AV_RL16(ptr);
		ptr += 2;
		mp_msg(MSGT_NETWORK, MSGL_V, " stream count=[0x%x][%u]\n",
		        stream_count, stream_count );
		for( i=0 ; i<stream_count ; i++ ) {
			uint32_t rate;
			int id;
			int j;
			if (ptr + 6 > end) goto len_err_out;
			id = AV_RL16(ptr);
			ptr += 2;
			rate = AV_RL32(ptr);
			ptr += 4;
			mp_msg(MSGT_NETWORK, MSGL_V,
                                "  stream id=[0x%x][%u]\n", id, id);
			mp_msg(MSGT_NETWORK, MSGL_V,
			        "  max bitrate=[0x%x][%u]\n", rate, rate);
			for (j = 0; j < asf_ctrl->n_video; j++) {
			  if (id == asf_ctrl->video_streams[j]) {
			    mp_msg(MSGT_NETWORK, MSGL_V, "  is video stream\n");
			    v_rates[j] = rate;
			    break;
			  }
			}
			for (j = 0; j < asf_ctrl->n_audio; j++) {
			  if (id == asf_ctrl->audio_streams[j]) {
			    mp_msg(MSGT_NETWORK, MSGL_V, "  is audio stream\n");
			    a_rates[j] = rate;
			    break;
			  }
			}
		}
  }
  free(buffer);

  // automatic stream selection based on bandwidth
  if (bw == 0) bw = INT_MAX;
  mp_msg(MSGT_NETWORK, MSGL_V, "Max bandwidth set to %d\n", bw);

  if (asf_ctrl->n_audio) {
    // find lowest-bitrate audio stream
    a_rate = a_rates[0];
    a_idx = 0;
    for (i = 0; i < asf_ctrl->n_audio; i++) {
      if (a_rates[i] < a_rate) {
        a_rate = a_rates[i];
        a_idx = i;
      }
    }
    if (max_idx(asf_ctrl->n_video, v_rates, bw - a_rate) < 0) {
      // both audio and video are not possible, try video only next
      a_idx = -1;
      a_rate = 0;
    }
  }
  // find best video stream
  v_idx = max_idx(asf_ctrl->n_video, v_rates, bw - a_rate);
  if (v_idx >= 0)
    v_rate = v_rates[v_idx];

  // find best audio stream
  a_idx = max_idx(asf_ctrl->n_audio, a_rates, bw - v_rate);

  free(v_rates);
  free(a_rates);

  if (a_idx < 0 && v_idx < 0) {
    mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_Bandwidth2SmallCannotPlay);
    return -1;
  }

  if (audio_id > 0)
    // a audio stream was forced
    asf_ctrl->audio_id = audio_id;
  else if (a_idx >= 0)
    asf_ctrl->audio_id = asf_ctrl->audio_streams[a_idx];
  else if (asf_ctrl->n_audio) {
    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedAudio);
    audio_id = -2;
  }

  if (video_id > 0)
    // a video stream was forced
    asf_ctrl->video_id = video_id;
  else if (v_idx >= 0)
    asf_ctrl->video_id = asf_ctrl->video_streams[v_idx];
  else if (asf_ctrl->n_video) {
    mp_msg(MSGT_NETWORK, MSGL_WARN, MSGTR_MPDEMUX_ASF_Bandwidth2SmallDeselectedVideo);
    video_id = -2;
  }

  return 1;

len_err_out:
  mp_msg(MSGT_NETWORK, MSGL_FATAL, MSGTR_MPDEMUX_ASF_InvalidLenInHeader);
  free(buffer);
  free(v_rates);
  free(a_rates);
  return -1;
}