示例#1
0
void CPlayerMedia::synchronize_rtp_bytestreams (rtcp_sync_t *sync)
{
  if (is_audio()) {
    player_error_message("Attempt to syncronize audio byte stream");
    return;
  }
  if (m_rtp_byte_stream != NULL) 
    m_rtp_byte_stream->synchronize(sync);
}
示例#2
0
int create_media_for_mpeg2t_file (CPlayerSession *psptr, 
				  const char *name,
				  int have_audio_driver, 
				  control_callback_vft_t *cc_vft)
{
  FILE *ifile;
  uint8_t buffer[188];

  ifile = fopen(name, FOPEN_READ_BINARY);
  if (ifile == NULL) {
    psptr->set_message("Couldn't open file %s", name);
    return -1;
  }

  if (fread(buffer, 1, 1, ifile) <= 0) {
    psptr->set_message("Couldn't read file %s", name);
    fclose(ifile);
    return -1;
  }
  if (buffer[0] != MPEG2T_SYNC_BYTE) {
    psptr->set_message("File is not mpeg2 transport %s", name);
    fclose(ifile);
    return -1;
  }
  CMpeg2tFile *tfile = new CMpeg2tFile(name, ifile);

  int ret;
  psptr->session_set_seekable(0);
  ret = tfile->create(psptr);
  if (ret < 0) {
    delete tfile;
    return ret;
  }
  ret = tfile->create_media(psptr, cc_vft);

  if (ret < 0) {
    player_error_message("mpeg2t file found");
    delete tfile;
  }
  psptr->set_session_desc(0, name);
  return ret;
}
int CMpeg2fVideoByteStream::get_timestamp_for_frame (mpeg2t_frame_t *fptr,
						     frame_timestamp_t *ts)

{
#ifdef DEBUG_MPEG2T_PSTS
  if (fptr->have_dts) {
    player_debug_message("video frame len %d have  dts %d ts "U64,
			 fptr->frame_len, fptr->have_dts, fptr->dts);
  } if (fptr->have_ps_ts) {
    player_debug_message("video frame len %d have psts %d ts "U64, 
			 fptr->frame_len, fptr->have_ps_ts, fptr->ps_ts);
  }
#endif
#if 0
  if (m_es_pid->stream_type == MPEG2T_STREAM_H264) {
    if (fptr->have_dts || fptr->have_ps_ts) {
      if (fptr->have_dts)
	outts = fptr->dts;
      else
	outts = fptr->ps_ts;
      outts *= TO_U64(1000);
      outts /= TO_U64(90000); // get msec from 90000 timescale
      return 0;
    }
    return -1;
  }
  uint64_t ts;
  //  m_es_pid->frame_rate = 24;
  double value = 90000.0 / m_es_pid->frame_rate;
  uint64_t frame_time = (uint64_t)value;
  if (fptr->have_ps_ts == 0 && fptr->have_dts == 0) {
    // We don't have a timestamp on this - just increment from
    // the previous timestamp.
    if (m_timestamp_loaded == 0) return -1;
    if (m_es_pid->info_loaded == 0) return -1;

    outts = m_prev_ts + frame_time;
    m_have_prev_frame_type = 1;
    m_prev_frame_type = fptr->frame_type;
    m_prev_ts = outts;
    outts *= TO_U64(1000);
    outts /= TO_U64(90000); // get msec from 90000 timescale
    return 0;
  }
  m_timestamp_loaded = 1;
  if (fptr->have_dts != 0) {
    outts = fptr->dts;
  } else {
    ts = fptr->ps_ts;

    if (m_have_prev_frame_type) {
      if (fptr->frame_type == 3) {
	// B frame
	outts = ts;
      } else {
	outts = m_prev_ts + frame_time;
      }
    } else {
      if (fptr->frame_type == 1) {
	uint16_t temp_ref = MP4AV_Mpeg3PictHdrTempRef(fptr->frame + fptr->pict_header_offset);
	ts -= ((temp_ref + 1) * m_es_pid->tick_per_frame);
	outts = ts;
      } else {
	player_error_message( "no psts and no prev frame");
	outts = ts;
      }
    }
  }

  m_have_prev_frame_type = 1;
  m_prev_frame_type = fptr->frame_type;
  m_prev_ts = outts;

  outts *= TO_U64(1000);
  outts /= TO_U64(90000); // get msec from 90000 timescale
  
  return 0;
#endif
  ts->timestamp_is_pts = fptr->have_dts == false;
  uint64_t outts;
  if (fptr->have_dts)
    outts = fptr->dts;
  else
    outts = fptr->ps_ts;
  outts *= TO_U64(1000);
  outts /= TO_U64(90000); // get msec from 90000 timescale
  ts->msec_timestamp = outts;
  return 0;
}
示例#4
0
bool CRtpByteStream::start_next_frame (uint8_t **buffer, 
				       uint32_t *buflen,
				       frame_timestamp_t *pts,
				       void **ud)
{
  uint16_t seq = 0;
  uint32_t rtp_ts = 0;
  uint64_t timetick;
  uint64_t ts = 0;
  int first = 0;
  int finished = 0;
  rtp_packet *rpak;
  int32_t diff;

  diff = m_buffer_len - m_bytes_used;

  if (diff >= 2) {
    // Still bytes in the buffer...
    *buffer = m_buffer + m_bytes_used;
    *buflen = diff;
#ifdef DEBUG_RTP_FRAMES
    rtp_message(LOG_DEBUG, "%s Still left - %d bytes", m_name, *buflen);
#endif
#if 0
    rtp_message(LOG_DEBUG, "%s start %02x %02x %02x %02x %02x", m_name,
		(*buffer)[0],
		(*buffer)[1],
		(*buffer)[2],
		(*buffer)[3],
		(*buffer)[4]);
#endif
    pts->msec_timestamp = m_last_realtime;
    pts->audio_freq_timestamp = m_last_rtp_ts;
    pts->audio_freq = m_timescale;
    pts->timestamp_is_pts = true;
    return true;
  } else {
    check_seq(m_head->rtp_pak_seq);

    m_buffer_len = 0;
    while (finished == 0) {
      rpak = m_head;
      if (rpak == NULL) { 
	// incomplete frame - bail on this
	player_error_message("%s - This should never happen - rtp bytestream"
			     "is incomplete and active", m_name);
	player_error_message("Please report to mpeg4ip");
	player_error_message("first %d seq %u ts %x blen %d",
			     first, seq, rtp_ts, m_buffer_len);
	m_buffer_len = 0;
	m_bytes_used = 0;
	return 0;
      }
	
      remove_packet_rtp_queue(rpak, 0);
      
      if (first == 0) {
	seq = rpak->rtp_pak_seq + 1;
	ts = rpak->pd.rtp_pd_timestamp;
	rtp_ts = rpak->rtp_pak_ts;
	first = 1;
      } else {
	if ((seq != rpak->rtp_pak_seq) ||
	    (rtp_ts != rpak->rtp_pak_ts)) {
	  if (seq != rpak->rtp_pak_seq) {
	    rtp_message(LOG_INFO, "%s missing rtp sequence - should be %u is %u", 
			m_name, seq, rpak->rtp_pak_seq);
	  } else {
	    rtp_message(LOG_INFO, "%s timestamp error - seq %u should be %x is %x", 
			m_name, seq, rtp_ts, rpak->rtp_pak_ts);
	  }
	  m_buffer_len = 0;
	  rtp_ts = rpak->rtp_pak_ts;
	}
	seq = rpak->rtp_pak_seq + 1;
      }
      uint8_t *from;
      uint32_t len;
      from = (uint8_t *)rpak->rtp_data + m_skip_on_advance_bytes;
      len = rpak->rtp_data_len - m_skip_on_advance_bytes;
      if ((m_buffer_len + len) >= m_buffer_len_max) {
	// realloc
	m_buffer_len_max = m_buffer_len + len + 1024;
	m_buffer = (uint8_t *)realloc(m_buffer, m_buffer_len_max);
      }
      memcpy(m_buffer + m_buffer_len, 
	     from,
	     len);
      m_buffer_len += len;
      if (rpak->rtp_pak_m == 1) {
	finished = 1;
      }
      set_last_seq(rpak->rtp_pak_seq);
      xfree(rpak);
    }
    m_bytes_used = 0;
    *buffer = m_buffer + m_bytes_used;
    *buflen = m_buffer_len - m_bytes_used;
#if 0
  rtp_message(LOG_DEBUG, "%s start %02x %02x %02x %02x %02x", m_name,
		  	(*buffer)[0],
		  	(*buffer)[1],
		  	(*buffer)[2],
		  	(*buffer)[3],
		  	(*buffer)[4]);
#endif
#ifdef DEBUG_RTP_FRAMES
    rtp_message(LOG_DEBUG, "%s buffer len %d", m_name, m_buffer_len);
#endif
  }
  timetick = rtp_ts_to_msec(rtp_ts, ts, m_wrap_offset);
  m_last_rtp_ts = rtp_ts;
  
  pts->msec_timestamp = timetick;
  pts->audio_freq_timestamp = m_last_rtp_ts;
  pts->audio_freq = m_timescale;
  pts->timestamp_is_pts = true;
  return (true);
}
示例#5
0
/*
 * Create the media for the quicktime file, and set up some session stuff.
 */
int create_media_for_avi_file (CPlayerSession *psptr, 
			       const char *name,
			       char *errmsg,
			       uint32_t errlen,
			       int have_audio_driver,
			       control_callback_vft_t *cc_vft)
{
  CAviFile *Avifile1 = NULL;
  avi_t *avi;
  CPlayerMedia *mptr;
  avi = AVI_open_input_file(name, 1);
  if (avi == NULL) {
    snprintf(errmsg, errlen, "%s", AVI_strerror());
    player_error_message("%s", AVI_strerror());
    return (-1);
  }

  int video_count = 1;
  codec_plugin_t *plugin;
  video_query_t vq;

  const char *codec_name = AVI_video_compressor(avi);
  player_debug_message("Trying avi video codec %s", codec_name);
  plugin = check_for_video_codec(STREAM_TYPE_AVI_FILE,
				 codec_name, 
				 NULL,
				 -1,
				 -1,
				 NULL,
				 0, 
				 &config);
  if (plugin == NULL) {
    video_count = 0;
  } else {
    vq.track_id = 1;
    vq.stream_type = STREAM_TYPE_AVI_FILE;
    vq.compressor = codec_name;
    vq.type = -1;
    vq.profile = -1;
    vq.fptr = NULL;
    vq.h = AVI_video_height(avi);
    vq.w = AVI_video_width(avi);
    vq.frame_rate = AVI_video_frame_rate(avi);
    vq.config = NULL;
    vq.config_len = 0;
    vq.enabled = 0;
    vq.reference = NULL;
  }

  int have_audio = 0;
  int audio_count = 0;
  audio_query_t aq;

  if (AVI_audio_bytes(avi) != 0) {
    have_audio = 1;
    plugin = check_for_audio_codec(STREAM_TYPE_AVI_FILE,
				   NULL,
				   NULL,
				   AVI_audio_format(avi), 
				   -1, 
				   NULL, 
				   0,
				   &config);
    if (plugin != NULL) {
      audio_count = 1;
      aq.track_id = 1;
      aq.stream_type = STREAM_TYPE_AVI_FILE;
      aq.compressor = NULL;
      aq.type = AVI_audio_format(avi);
      aq.profile = -1;
      aq.fptr = NULL;
      aq.sampling_freq = AVI_audio_rate(avi);
      aq.chans = AVI_audio_channels(avi);
      aq.config = NULL;
      aq.config_len = 0;
      aq.enabled = 0;
      aq.reference = NULL;
    }
  }

  if (cc_vft != NULL && cc_vft->media_list_query != NULL) {
    (cc_vft->media_list_query)(psptr, video_count, &vq, audio_count, &aq);
  } else {
    if (video_count != 0) vq.enabled = 1;
    if (audio_count != 0) aq.enabled = 1;
  }


  if ((video_count == 0 || vq.enabled == 0) && 
      (audio_count == 0 || aq.enabled == 0)) {
    snprintf(errmsg, errlen, "No audio or video tracks enabled or playable");
    AVI_close(avi);
    return -1;
  }
  
  Avifile1 = new CAviFile(name, avi, vq.enabled, audio_count);
  psptr->set_media_close_callback(close_avi_file, Avifile1);

  if (video_count != 0 && vq.enabled) {
    mptr = new CPlayerMedia(psptr);
    if (mptr == NULL) {
      return (-1);
    }
  
    video_info_t *vinfo = MALLOC_STRUCTURE(video_info_t);
    if (vinfo == NULL) 
      return (-1);
    vinfo->height = vq.h;
    vinfo->width = vq.w;
    player_debug_message("avi file h %d w %d frame rate %g", 
			 vinfo->height,
			 vinfo->width,
			 vq.frame_rate);

    plugin = check_for_video_codec(STREAM_TYPE_AVI_FILE,
				   codec_name, 
				   NULL,
				   -1,
				   -1,
				   NULL,
				   0,
				   &config);
    int ret;
    ret = mptr->create_video_plugin(plugin,
				    STREAM_TYPE_AVI_FILE,
				    codec_name,
				    -1,
				    -1,
				    NULL,
				    vinfo,
				    NULL,
				    0);
    if (ret < 0) {
      snprintf(errmsg, errlen, "Failed to create video plugin %s", 
	       codec_name);
      player_error_message("Failed to create plugin data");
      delete mptr;
      return -1;
    }
    CAviVideoByteStream *vbyte = new CAviVideoByteStream(Avifile1);
    if (vbyte == NULL) {
      delete mptr;
      return (-1);
    }
    vbyte->config(AVI_video_frames(avi), vq.frame_rate);
    ret = mptr->create(vbyte, TRUE, errmsg, errlen);
    if (ret != 0) {
      return (-1);
    }
  }
    
  int seekable = 1;
  if (have_audio_driver > 0 && audio_count > 0 && aq.enabled != 0) {
    plugin = check_for_audio_codec(STREAM_TYPE_AVI_FILE,
				   NULL,
				   NULL,
				   aq.type,
				   -1, 
				   NULL, 
				   0,
				   &config);
    CAviAudioByteStream *abyte;
    mptr = new CPlayerMedia(psptr);
    if (mptr == NULL) {
      return (-1);
    }
    audio_info_t *ainfo;
    ainfo = MALLOC_STRUCTURE(audio_info_t);
    ainfo->freq = aq.sampling_freq;
    ainfo->chans = aq.chans;
    ainfo->bitspersample = AVI_audio_bits(avi); 

  
    int ret;
    ret = mptr->create_audio_plugin(plugin, 
				    aq.stream_type,
				    aq.compressor,
				    aq.type,
				    aq.profile,
				    NULL, 
				    ainfo,
				    NULL, 
				    0);
    if (ret < 0) {
      delete mptr;
      player_error_message("Couldn't create audio from plugin %s", 
			   plugin->c_name);
      return -1;
    }
    abyte = new CAviAudioByteStream(Avifile1);

    ret = mptr->create(abyte, FALSE, errmsg, errlen);
    if (ret != 0) {
      return (-1);
    }
    seekable = 0;
  } 
  psptr->session_set_seekable(seekable);

  if (audio_count == 0 && have_audio != 0) {
    snprintf(errmsg, errlen, "Unknown Audio Codec in avi file ");
    return (1);
  }
  if (video_count != 1) {
    snprintf(errmsg, errlen, "Unknown Video Codec %s in avi file",
	     codec_name);
    return (1);
  }
  return (0);
}
示例#6
0
/*
 * Create - will determine pids and psts ranges in file.  Will also
 * loop through the file and determine CFilePosRec points at percentages
 */
int CMpeg2tFile::create (CPlayerSession *psptr)
{
  m_mpeg2t = create_mpeg2_transport();
  if (m_mpeg2t == NULL) {
    psptr->set_message("Couldn't create mpeg2 transport");
    fclose(m_ifile);
    return -1;
  }
  // nice, large buffers to process
  m_buffer_size_max = 188 * 2000;
  m_buffer = (uint8_t *)malloc(m_buffer_size_max);

  if (m_buffer == NULL) {
    psptr->set_message("Malloc error");
    return -1;
  }
  m_buffer[0] = MPEG2T_SYNC_BYTE;
  m_buffer_size = fread(&m_buffer[1], 1, m_buffer_size_max - 1, m_ifile) + 1;

  bool done = false;
  mpeg2t_pid_t *pidptr;
  uint32_t buflen_used;
  bool have_psts = false;
  uint64_t earliest_psts = 0;
  mpeg2t_es_t *es_pid;

  int olddebuglevel;
  olddebuglevel = config.get_config_value(CONFIG_MPEG2T_DEBUG);
  if (olddebuglevel != LOG_DEBUG)
    mpeg2t_set_loglevel(LOG_CRIT);
  m_mpeg2t->save_frames_at_start = 1;
  /*
   * We need to determine which PIDs are present, and try to establish
   * a starting psts.  We also want to establish what type of video and
   * audio are in the mix.  Note: if we try to run this on a file that
   * we don't understand the video, this could take a while, because the
   * info never gets loaded.
   */
  do {
    m_buffer_on = 0;
    while (m_buffer_on + 188 < m_buffer_size && done == false) {
      
      pidptr = mpeg2t_process_buffer(m_mpeg2t, 
				     &m_buffer[m_buffer_on],
				     m_buffer_size - m_buffer_on,
				     &buflen_used);
      m_buffer_on += buflen_used;
      if (pidptr != NULL && pidptr->pak_type == MPEG2T_ES_PAK) {
	es_pid = (mpeg2t_es_t *)pidptr;
	mpeg2t_frame_t *fptr;

	// determine earliest PS_TS
	while ((fptr = mpeg2t_get_es_list_head(es_pid)) != NULL) {
	  if (fptr->have_ps_ts != 0 || fptr->have_dts != 0) {
	    uint64_t ps_ts = 0;
	    bool store_psts = true;
	    if (fptr->have_dts != 0) {
	      ps_ts = fptr->dts;
	    } else {
	      if (es_pid->is_video == 1) { // mpeg2
		// video - make sure we get the first I frame, then we can
		// get the real timestamp
		if (fptr->frame_type != 1) {
		  store_psts = false;
		} else {
		  ps_ts = fptr->ps_ts;
		  uint16_t temp_ref = MP4AV_Mpeg3PictHdrTempRef(fptr->frame + fptr->pict_header_offset);
		  ps_ts -= ((temp_ref + 1) * es_pid->tick_per_frame);
		}
	      } else {
		ps_ts = fptr->ps_ts;
	      }
	    }
	    if (store_psts) {
	      // when we have the first psts for a ES_PID, turn off
	      // parsing frames for that PID.
	      mpeg2t_set_frame_status(es_pid, MPEG2T_PID_NOTHING);
	      if (have_psts) {
		earliest_psts = MIN(earliest_psts, ps_ts);
	      } else {
		earliest_psts = ps_ts;
		have_psts = true;
	      }
	    }
	  }
	  mpeg2t_free_frame(fptr);
	}

	// Each time, search through and see if there are any ES_PIDs 
	// that have not returned a psts.  We're done when the info is
	// loaded for all the es pids.
	pidptr = m_mpeg2t->pas.pid.next_pid;
	bool finished = true;
	while (pidptr != NULL && finished) {
	  if (pidptr->pak_type == MPEG2T_ES_PAK) {
	    es_pid = (mpeg2t_es_t *)pidptr;
	    if (es_pid->info_loaded == 0) {
	      finished = false;
	    }
	  }
	  pidptr = pidptr->next_pid;
	}
	done = finished || have_psts;
      }
    }
    if (done == false) {
      m_buffer_size = fread(m_buffer, 1, m_buffer_size_max, m_ifile);
    }
  } while (m_buffer_size >=188 && done == false);

  if (done == false) {
    psptr->set_message("Could not find information in TS");
    mpeg2t_set_loglevel(olddebuglevel);
    return -1;
  }

#ifdef DEBUG_MPEG2F_SEARCH
  mpeg2f_message(LOG_DEBUG, "initial psts is "U64, earliest_psts);
#endif
  m_start_psts = earliest_psts;

  // Now, we'll try to build a rough index for the file
  // enable psts reading for the pid
  for (pidptr = m_mpeg2t->pas.pid.next_pid; pidptr != NULL; pidptr = pidptr->next_pid) {
    if (pidptr->pak_type == MPEG2T_ES_PAK) {
      es_pid = (mpeg2t_es_t *)pidptr;
      mpeg2t_set_frame_status(es_pid, MPEG2T_PID_REPORT_PSTS);
    }
  }
  m_file_record.record_point(0, earliest_psts, 0);
  fpos_t fpos;
  uint64_t end;
  uint64_t perc, cur;

  // find out the length of the file.
  struct stat filestat;
  if (fstat(fileno(m_ifile), &filestat) != 0) {
    return -1;
  }
  end = filestat.st_size;
  perc = end;
  // perc is what size of the file to skip through to get a rough
  // timetable.  We want to do 10% chunks, or 100Mb chunks, whichever is
  // less.
  while (perc > TO_U64(100000000)) {
    perc /= 2;
  }
  if (perc > (end / TO_U64(10))) {
    perc = end / TO_U64(10);
  }
  if (perc < (end / TO_U64(50))) {
    perc = end / TO_U64(50);
  }
#ifdef DEBUG_MPEG2F_SEARCH
  mpeg2f_message(LOG_DEBUG, "perc is "U64" "U64, perc, (perc * TO_U64(100)) / end );
#endif

  cur = perc;

  bool is_seekable = true;
  uint64_t last_psts, ts;
  last_psts = earliest_psts;

  // Now - skip to the next perc chunk, and try to find the next psts
  // we'll record this info.
  do {
#ifdef DEBUG_MPEG2F_SEARCH
    mpeg2f_message(LOG_DEBUG, "current "U64" end "U64, cur, end);
#endif
    VAR_TO_FPOS(fpos, cur);
    fsetpos(m_ifile, &fpos);
    done = false;
    uint64_t count = 0;
    m_buffer_on = 0;
    m_buffer_size = 0;
    do {
      if (m_buffer_on + 188 > m_buffer_size) {
	if (m_buffer_on < m_buffer_size) {
	  memmove(m_buffer, m_buffer + m_buffer_on, 
		  m_buffer_size - m_buffer_on);
	  m_buffer_on = m_buffer_size - m_buffer_on;
	} else {
	  m_buffer_on = 0;
	}
	m_buffer_size = fread(m_buffer + m_buffer_on, 
			      1, 
			      (188 * 10) - m_buffer_on, 
			      m_ifile);

	count += m_buffer_size - m_buffer_on;
	m_buffer_size += m_buffer_on;
	m_buffer_on = 0;
	if (m_buffer_size < 188) {
	  m_buffer_size = 0;
	  done = true;
	}
      }

      pidptr = mpeg2t_process_buffer(m_mpeg2t,
				     m_buffer + m_buffer_on, 
				     m_buffer_size - m_buffer_on, 
				     &buflen_used);
      m_buffer_on += buflen_used;
      if (pidptr != NULL && pidptr->pak_type == MPEG2T_ES_PAK) {
	es_pid = (mpeg2t_es_t *)pidptr;
	// If we have a psts, record it.
	// If it is less than the previous one, we've got a discontinuity, so
	// we can't seek.
	if (es_pid->have_ps_ts || es_pid->have_dts) {
	  ts = es_pid->have_ps_ts ? es_pid->ps_ts : es_pid->dts;
	  if (ts < last_psts) {
	    player_error_message("pid %x psts "U64" is less than prev record point "U64, 
				 es_pid->pid.pid, ts, last_psts);
	    cur = end;
	    is_seekable = false;
	  } else {
#ifdef DEBUG_MPEG2F_SEARCH
	    mpeg2f_message(LOG_DEBUG, "pid %x psts "U64" %d", 
			       pidptr->pid, ts, 
			       es_pid->is_video);
#endif
	    m_file_record.record_point(cur, ts, 0);
	  }
	  done = true;
	}
      }

    } while (done == false && count < perc / 2);
    cur += perc;

  } while (cur < end - (m_buffer_size_max * 2));

  //mpeg2f_message(LOG_DEBUG, "starting end search");
  // Now, we'll go to close to the end of the file, and look for a 
  // final PSTS.  This gives us a rough estimate of the elapsed time
  long seek_offset;
  seek_offset = 0;
  seek_offset -= (m_buffer_size_max) * 2;
  fseek(m_ifile, seek_offset, SEEK_END);
  m_buffer_on = m_buffer_size = 0;
  uint64_t max_psts;
  max_psts = m_start_psts;
  do {
    while (m_buffer_on + 188 <= m_buffer_size) {
      
      pidptr = mpeg2t_process_buffer(m_mpeg2t, 
				     &m_buffer[m_buffer_on],
				     m_buffer_size - m_buffer_on,
				     &buflen_used);
      m_buffer_on += buflen_used;
      if (pidptr != NULL && pidptr->pak_type == MPEG2T_ES_PAK) {
	es_pid = (mpeg2t_es_t *)pidptr;
	if (es_pid->have_ps_ts) {
	  es_pid->have_ps_ts = 0;
	  max_psts = MAX(es_pid->ps_ts, max_psts);
	} else if (es_pid->have_dts) {
	  es_pid->have_dts = 0;
	  max_psts = MAX(es_pid->dts, max_psts);
	}
      }
    }
    if (m_buffer_size > m_buffer_on) {
      memmove(m_buffer, m_buffer + m_buffer_on, m_buffer_size - m_buffer_on);
    }
    m_buffer_on = m_buffer_size - m_buffer_on;
    m_buffer_size = fread(m_buffer + m_buffer_on, 1, 
			  m_buffer_size_max - m_buffer_on, m_ifile);
    m_buffer_size += m_buffer_on;
    m_buffer_on = 0;
    if (m_buffer_size < 188) m_buffer_size = 0;
  } while (m_buffer_size > 188) ;
  m_last_psts = max_psts;
  // Calculate the rough max time; hopefully it will be greater than the
  // initial...
  m_max_time = max_psts;
  m_max_time -= m_start_psts;
  m_max_time /= 90000.0;
#ifdef DEBUG_MPEG2F_SEARCH
  player_debug_message("last psts is "U64" "U64" %g", max_psts,
		       (max_psts - m_start_psts) / TO_U64(90000),
		       m_max_time);
#endif
  mpeg2t_set_loglevel(olddebuglevel);

  if (is_seekable) {
    psptr->session_set_seekable(1);
  }
  m_ts_seeked_in_msec = UINT64_MAX;
  rewind(m_ifile);

  return 0;
}
示例#7
0
int main (int argc, char **argv)
{
	SDL_sem *master_sem;
	CClientProcess proc;
	CMsgQueue master_queue;

	argv++;
	argc--;
	int deb = 0;
	if (*argv[0] == '-') {
		argv++;
		argc--;
		deb = 1;
	}
	
	open_output("wmp4player.log");
	if (proc.enable_communication(deb) < 0) {
		printf("Could not enable communications\n");
		Sleep(10 * 1000);
		close_output();
		return -1;
	}
	initialize_plugins(&config);
	config.InitializeIndexes();
	config.ReadVariablesFromRegistry("Software\\Mpeg4ip", "Config");

	psptr = NULL;
	master_sem = NULL;
	if (*argv == NULL) {
		proc.initial_response(-1, psptr,"No argument to process");
	} else {
		rtsp_set_error_func(library_message);
		rtp_set_error_msg_func(library_message);
		sdp_set_error_func(library_message);
		http_set_error_func(library_message);
	
		master_sem = SDL_CreateSemaphore(0);
			
		psptr = start_session(&master_queue, 
							  master_sem, 
							  NULL,
							  *argv,
							  NULL,
							  config.get_config_value(CONFIG_VOLUME),
			                  100, 
			                  100,
			                  screen_size);
		if (psptr == NULL) {
			proc.initial_response(-1, NULL, NULL);
		} else {
		proc.initial_response(0, psptr, psptr->get_message());
		}
	}
	// Either way - we need to loop and wait until we get the
	// terminate message
	int running = 0;
	int state = 0;
	while (running == 0) {
		CMsg *msg;
		running = proc.receive_messages(psptr);
		while ((msg = master_queue.get_message()) != NULL) {
			switch (msg->get_value()) {
			case MSG_SESSION_FINISHED:
				proc.send_message(GUI_MSG_SESSION_FINISHED);
				break;
			case MSG_SESSION_WARNING:
				proc.send_string(GUI_MSG_SESSION_WARNING, psptr->get_message());
				break;
			case MSG_SESSION_ERROR:
				player_error_message("error is \"%s\"", psptr->get_message());
				proc.send_string(GUI_MSG_SESSION_ERROR, psptr->get_message());
				break;
			case MSG_RECEIVED_QUIT:
				proc.send_message(GUI_MSG_RECEIVED_QUIT);
				break;
			case MSG_SDL_KEY_EVENT:
				uint32_t len;
				void *sdl_event = (void *)msg->get_message(len);
				proc.send_message(GUI_MSG_SDL_KEY,
								  sdl_event,
								  len);
				break;
			}
			delete msg;
		}
		if (psptr != NULL) state = psptr->sync_thread(state);
	}
	if (psptr != NULL) {
		delete psptr;
	}
	if (master_sem != NULL) {
		SDL_DestroySemaphore(master_sem);
	}
	  // remove invalid global ports
	

	config.WriteVariablesToRegistry("Software\\Mpeg4ip", "Config");
	close_plugins();
	close_output();
	return 0;
}
示例#8
0
/*
 * C2ConsecIpPort::C2ConsecIpPort() - get 2 consecutive, even-odd, ip
 * port numbers
 */
C2ConsecIpPort::C2ConsecIpPort (CIpPort **global, in_port_t start_port)
{
  CIpPort *newone;
  m_first = m_second = NULL;
  in_port_t firstport, maxport;

  maxport = (in_port_t)~0;
  if (start_port == 0) {
    firstport = 1024;
    if (config.get_config_value(CONFIG_IPPORT_MIN) != UINT32_MAX) {
      firstport = config.get_config_value(CONFIG_IPPORT_MIN);
      if (config.get_config_value(CONFIG_IPPORT_MAX) != UINT32_MAX) {
	maxport = config.get_config_value(CONFIG_IPPORT_MAX);
	if (maxport <= firstport) {
	  player_error_message("IP port configuration error - %u %u - using 65535 as max port value", 
			       firstport, maxport);
	  maxport = (in_port_t)~0;
	}
      }
    }
  } else {
    firstport = start_port;
  }
  while (1) {
    // first, get an even port number.  If not even, save it in the
    // global queue.
    do {
      newone = new CIpPort(firstport, maxport);
      if (newone->valid() == 0)
	return;
      if ((newone->get_port_num() & 0x1) == 0x1) {
	newone->set_next(*global);
	*global = newone;
	firstport++;
      }
    } while ((newone->get_port_num() & 0x1) == 0x1);

    player_debug_message("First port is %d", newone->get_port_num());

    // Okay, save the first, get the 2nd.  If okay, just return
    m_first = newone;
    in_port_t next;
    next = m_first->get_port_num() + 1;
    m_second = new CIpPort(next, next);
    if ((m_second->valid() == 1) &&
	(m_second->get_port_num() == next)) {
      player_debug_message("Ip ports are %u %u", next - 1, next);
      return;
    } else {
      player_debug_message("Got port %d invalid %d", m_second->get_port_num(),
			   m_second->valid());
    }
    // Not okay - save both off in the global queue, and try again...
    m_first->set_next(*global);
    *global = m_first;
    m_first = NULL;
    firstport = m_second->get_port_num() + 1;
    m_second->set_next(*global);
    *global = m_second;
    m_second = NULL;
  }
}
/*
 * play_all_media - get all media to play
 */
int CPlayerSession::play_all_media (int start_from_begin, 
				    double start_time,
				    char *errmsg, 
				    uint32_t errlen)
{
  int ret;
  CPlayerMedia *p;

  if (m_set_end_time == 0) {
    range_desc_t *range;
    if (m_sdp_info && m_sdp_info->session_range.have_range != FALSE) {
      range = &m_sdp_info->session_range;
    } else {
      range = NULL;
      p = m_my_media;
      while (range == NULL && p != NULL) {
	media_desc_t *media;
	media = p->get_sdp_media_desc();
	if (media && media->media_range.have_range) {
	  range = &media->media_range;
	}
	p = p->get_next();
      }
    }
    if (range != NULL) {
      m_end_time = (uint64_t)(range->range_end * 1000.0);
      m_set_end_time = 1;
    }
  }
  p = m_my_media;
  m_session_state = SESSION_BUFFERING;
  if (m_paused == 1 && start_time == 0.0 && start_from_begin == FALSE) {
    /*
     * we were paused.  Continue.
     */
    m_play_start_time = m_current_time;
    start_time = UINT64_TO_DOUBLE(m_current_time);
    start_time /= 1000.0;
    player_debug_message("Restarting at " U64 ", %g", m_current_time, start_time);
  } else {
    /*
     * We might have been paused, but we're told to seek
     */
    // Indicate what time we're starting at for sync task.
    m_play_start_time = (uint64_t)(start_time * 1000.0);
  }
  m_paused = 0;

  send_sync_thread_a_message(MSG_START_SESSION);
  // If we're doing aggregate rtsp, send the play command...

  if (session_control_is_aggregate() &&
      m_dont_send_first_rtsp_play == 0) {
    char buffer[80];
    rtsp_command_t cmd;
    rtsp_decode_t *decode;

    memset(&cmd, 0, sizeof(rtsp_command_t));
    if (m_set_end_time != 0) {
      uint64_t stime = (uint64_t)(start_time * 1000.0);
      sprintf(buffer, "npt="U64"."U64"-"U64"."U64, 
	      stime / 1000, stime % 1000, m_end_time / 1000, m_end_time % 1000);
      cmd.range = buffer;
    }
    if (rtsp_send_aggregate_play(m_rtsp_client,
				 m_session_control_url,
				 &cmd,
				 &decode) != 0) {
      if (errmsg != NULL) {
	snprintf(errmsg, errlen, "RTSP Aggregate Play Error %s-%s", 
		 decode->retcode,
		 decode->retresp != NULL ? decode->retresp : "");
      }
      player_debug_message("RTSP aggregate play command failed");
      free_decode_response(decode);
      return (-1);
    }
    if (decode->rtp_info == NULL) {
      player_error_message("No rtp info field");
    } else {
      player_debug_message("rtp info is \'%s\'", decode->rtp_info);
    }
    int ret = process_rtsp_rtpinfo(decode->rtp_info, this, NULL);
    free_decode_response(decode);
    if (ret < 0) {
      if (errmsg != NULL) {
	snprintf(errmsg, errlen, "RTSP aggregate RtpInfo response failure");
      }
      player_debug_message("rtsp aggregate rtpinfo failed");
      return (-1);
    }
  }
  m_dont_send_first_rtsp_play = 0;

  while (p != NULL) {
    ret = p->do_play(start_time, errmsg, errlen);
    if (ret != 0) return (ret);
    p = p->get_next();
  }
  return (0);
}
示例#10
0
/*
 * create_streaming - create a session for streaming.  Create an
 * RTSP session with the server, get the SDP information from it.
 */
int CPlayerSession::create_streaming_ondemand (const char *url, 
					       char *errmsg,
					       uint32_t errlen, 
					       int use_tcp)
{
  rtsp_command_t cmd;
  rtsp_decode_t *decode;
  sdp_decode_info_t *sdpdecode;
  int dummy;
  int err;

  // streaming has seek capability (at least on demand)
  session_set_seekable(1);
  player_debug_message("Creating streaming %s", url);
  memset(&cmd, 0, sizeof(rtsp_command_t));

  /*
   * create RTSP session
   */
  if (use_tcp != 0) {
    m_rtsp_client = rtsp_create_client_for_rtp_tcp(url, &err);
  } else {
    m_rtsp_client = rtsp_create_client(url, &err);
  }
  if (m_rtsp_client == NULL) {
    snprintf(errmsg, errlen, "Failed to create RTSP client");
    player_error_message("Failed to create rtsp client - error %d", err);
    return (err);
  }
  m_rtp_over_rtsp = use_tcp;

  cmd.accept = "application/sdp";

  /*
   * Send the RTSP describe.  This should return SDP information about
   * the session.
   */
  int rtsp_resp;

  rtsp_resp = rtsp_send_describe(m_rtsp_client, &cmd, &decode);
  if (rtsp_resp != RTSP_RESPONSE_GOOD) {
    int retval;
    if (decode != NULL) {
      retval = (((decode->retcode[0] - '0') * 100) +
		((decode->retcode[1] - '0') * 10) +
		(decode->retcode[2] - '0'));
      snprintf(errmsg, errlen, "RTSP describe error %d %s", retval,
	       decode->retresp != NULL ? decode->retresp : "");
      free_decode_response(decode);
    } else {
      retval = -1;
      snprintf(errmsg, errlen, "RTSP return invalid %d", rtsp_resp);
    }
    player_error_message("Describe response not good\n");
    return (retval);
  }

  sdpdecode = set_sdp_decode_from_memory(decode->body);
  if (sdpdecode == NULL) {
    snprintf(errmsg, errlen, "Memory failure");
    player_error_message("Couldn't get sdp decode\n");
    free_decode_response(decode);
    return (-1);
  }

  /*
   * Decode the SDP information into structures we can use.
   */
  err = sdp_decode(sdpdecode, &m_sdp_info, &dummy);
  free(sdpdecode);
  if (err != 0) {
    snprintf(errmsg, errlen, "Couldn't decode session description %s",
	     decode->body);
    player_error_message("Couldn't decode sdp %s", decode->body);
    free_decode_response(decode);
    return (-1);
  }
  if (dummy != 1) {
    snprintf(errmsg, errlen, "Incorrect number of sessions in sdp decode %d",
	     dummy);
    player_error_message("%s", errmsg);
    free_decode_response(decode);
    return (-1);
  }

  /*
   * Make sure we can use the urls in the sdp info
   */
  if (decode->content_location != NULL) {
    // Note - we may have problems if the content location is not absolute.
    m_content_base = strdup(decode->content_location);
  } else if (decode->content_base != NULL) {
    m_content_base = strdup(decode->content_base);
  } else {
    int urllen = strlen(url);
    if (url[urllen] != '/') {
      char *temp;
      temp = (char *)malloc(urllen + 2);
      strcpy(temp, url);
      strcat(temp, "/");
      m_content_base = temp;
    } else {
      m_content_base = strdup(url);
    }
  }

  convert_relative_urls_to_absolute(m_sdp_info,
				    m_content_base);

  if (m_sdp_info->control_string != NULL) {
    player_debug_message("setting control url to %s", m_sdp_info->control_string);
    set_session_control_url(m_sdp_info->control_string);
  }
  free_decode_response(decode);
  m_streaming = 1;
  m_streaming_ondemand = (get_range_from_sdp(m_sdp_info) != NULL);
  return (0);
}
示例#11
0
static int create_media_from_sdp (CPlayerSession *psptr,
                                  session_desc_t *sdp,
                                  char *errmsg,
                                  uint32_t errlen,
                                  int have_audio_driver,
                                  int broadcast,
                                  int only_check_first,
                                  control_callback_vft_t *cc_vft)
{
    int err;
    int media_count = 0;
    int invalid_count = 0;
    int have_audio_but_no_driver = 0;
    char buffer[80];
    codec_plugin_t *codec;
    format_list_t *fmt;
    int audio_count, video_count;
    int audio_offset, video_offset;
    int ix;

    if (sdp->session_name != NULL) {
        snprintf(buffer, sizeof(buffer), "Name: %s", sdp->session_name);
        psptr->set_session_desc(0, buffer);
    }
    if (sdp->session_desc != NULL) {
        snprintf(buffer, sizeof(buffer), "Description: %s", sdp->session_desc);
        psptr->set_session_desc(1, buffer);
    }
#ifndef _WIN32
    if (sdp->media != NULL &&
            sdp->media->next == NULL &&
            strcasecmp(sdp->media->media, "video") == 0 &&
            sdp->media->fmt != NULL &&
            strcmp(sdp->media->fmt->fmt, "33") == 0) {
        // we have a mpeg2 transport stream
        return (create_mpeg2t_session(psptr, NULL, sdp, errmsg, errlen,
                                      have_audio_driver, cc_vft));

    }
#endif
    media_desc_t *sdp_media;
    audio_count = video_count = 0;
    for (sdp_media = psptr->get_sdp_info()->media;
            sdp_media != NULL;
            sdp_media = sdp_media->next) {
        if (strcasecmp(sdp_media->media, "audio") == 0) {
            if (have_audio_driver == 0) {
                have_audio_but_no_driver = 1;
            } else {
                audio_count++;
            }
        } else if (strcasecmp(sdp_media->media, "video") == 0) {
            video_count++;
        }
    }

    video_query_t *vq;
    audio_query_t *aq;

    if (video_count > 0) {
        vq = (video_query_t *)malloc(sizeof(video_query_t) * video_count);
    } else {
        vq = NULL;
    }
    if (audio_count > 0) {
        aq = (audio_query_t *)malloc(sizeof(audio_query_t) * audio_count);
    } else {
        aq = NULL;
    }

    video_offset = audio_offset = 0;
    for (sdp_media = psptr->get_sdp_info()->media;
            sdp_media != NULL;
            sdp_media = sdp_media->next) {

        if (have_audio_driver != 0 &&
                strcasecmp(sdp_media->media, "audio") == 0) {
            fmt = sdp_media->fmt;
            codec = NULL;
            while (codec == NULL && fmt != NULL) {
                codec = check_for_audio_codec(STREAM_TYPE_RTP,
                                              NULL,
                                              fmt,
                                              -1,
                                              -1,
                                              NULL,
                                              0,
                                              &config);
                if (codec == NULL) {
                    if (only_check_first != 0)
                        fmt = NULL;
                    else
                        fmt = fmt->next;
                }
            }
            if (codec == NULL) {
                invalid_count++;
                continue;
            } else {
                // set up audio qualifier
                aq[audio_offset].track_id = audio_offset;
                aq[audio_offset].stream_type = STREAM_TYPE_RTP;
                aq[audio_offset].compressor = NULL;
                aq[audio_offset].type = -1;
                aq[audio_offset].profile = -1;
                aq[audio_offset].fptr = fmt;
                aq[audio_offset].sampling_freq = -1;
                aq[audio_offset].chans = -1;
                aq[audio_offset].enabled = 0;
                aq[audio_offset].reference = NULL;
                audio_offset++;
            }
        } else if (strcasecmp(sdp_media->media, "video") == 0) {
            fmt = sdp_media->fmt;
            codec = NULL;
            while (codec == NULL && fmt != NULL) {
                codec = check_for_video_codec(STREAM_TYPE_RTP,
                                              NULL,
                                              fmt,
                                              -1,
                                              -1,
                                              NULL,
                                              0,
                                              &config);
                if (codec == NULL) {
                    if (only_check_first != 0)
                        fmt = NULL;
                    else
                        fmt = fmt->next;
                }
            }
            if (codec == NULL) {
                invalid_count++;
                continue;
            } else {
                vq[video_offset].track_id = video_offset;
                vq[video_offset].stream_type = STREAM_TYPE_RTP;
                vq[video_offset].compressor = NULL;
                vq[video_offset].type = -1;
                vq[video_offset].profile = -1;
                vq[video_offset].fptr = fmt;
                vq[video_offset].h = -1;
                vq[video_offset].w = -1;
                vq[video_offset].frame_rate = -1;
                vq[video_offset].enabled = 0;
                vq[video_offset].reference = NULL;
                video_offset++;
            }
        } else {
            player_error_message("Skipping media type `%s\'", sdp_media->media);
            continue;
        }
    }
    // okay - from here, write the callback call, and go ahead...
    if (cc_vft != NULL &&
            cc_vft->media_list_query != NULL) {
        (cc_vft->media_list_query)(psptr, video_offset, vq, audio_offset, aq);
    } else {
        if (video_offset > 0) {
            vq[0].enabled = 1;
        }
        if (audio_offset > 0) {
            aq[0].enabled = 1;
        }
    }
    for (ix = 0; ix < video_offset; ix++) {
        if (vq[ix].enabled != 0) {
            CPlayerMedia *mptr = new CPlayerMedia(psptr);
            err = mptr->create_streaming(vq[ix].fptr->media,
                                         errmsg,
                                         errlen,
                                         broadcast,
                                         config.get_config_value(CONFIG_USE_RTP_OVER_RTSP),
                                         media_count);
            if (err < 0) {
                return (-1);
            }
            if (err > 0) {
                delete mptr;
            } else
                media_count++;
        }
    }
    for (ix = 0; ix < audio_offset; ix++) {
        if (aq[ix].enabled != 0) {
            CPlayerMedia *mptr = new CPlayerMedia(psptr);
            err = mptr->create_streaming(aq[ix].fptr->media,
                                         errmsg,
                                         errlen,
                                         broadcast,
                                         config.get_config_value(CONFIG_USE_RTP_OVER_RTSP),
                                         media_count);
            if (err < 0) {
                return (-1);
            }
            if (err > 0) {
                delete mptr;
            } else
                media_count++;
        }
    }
    if (aq != NULL) free(aq);
    if (vq != NULL) free(vq);

    if (media_count == 0) {
        snprintf(errmsg, errlen, "No known codecs found in SDP");
        return (-1);
    }
    psptr->streaming_media_set_up();
    if (have_audio_but_no_driver > 0) {
        snprintf(errmsg, errlen, "Not playing audio codecs - no driver");
        return (1);
    }
    if (invalid_count > 0) {
        snprintf(errmsg, errlen,
                 "There were unknowns codecs during decode - playing valid ones");
        return (1);
    }
    return (0);
}