www.pudn.com > RTP通用开发库(for Linux).rar > main.c


/*-------------------------------------------------------------------------
 * main.c - main
 *-------------------------------------------------------------------------
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include "main.h"

#ifdef SOLARIS
#include 
#endif /* SOLARIS */

#ifdef LINUX
#include 
#endif /* LINUX */

#define MAX_SOURCES 32

/*
 * Uncomment the line below if building 
 * with MPEG audio support.
 */
/*#define MPEG*/

/*-----------------------------------------------------------------------
 * main - wait for audio and play if possible
 *-----------------------------------------------------------------------
 */
int main(int argc, char **argv) {
  
  char			buf[4000];
  unsigned short	*samp16 = (unsigned short *) buf;
  bool			found;
  int			audio, port, rv, payloadtype;
  int			count, i, encoding = 0, one = 1;
  ssrc_t		ssrc = 0, sources[MAX_SOURCES];
  struct in_addr	addr;
  struct session	*psn;
  struct synsession	*pssn;
  struct timespec	time;
  struct sampparam	parameters;
  struct encoding	enc;
  mediatime_t		ts;
  struct sampreadparam  sreadparam;

#ifdef SOLARIS
  audio_info_t		audio_info;
#endif /* SOLARIS */

#ifdef LINUX
  int			leeway;
#endif /* LINUX */
  
#ifdef MPEG
  struct		frameparam fparameters;
#endif /* MPEG */

  /*
   * Check for correct number of arguments.
   */
  if (argc != 3) {
    fprintf(stderr, "Usage: %s  \n", argv[0]);
    exit(0);
  }
  
  addr.s_addr = inet_addr(argv[1]);
  port = atoi(argv[2]);

  printf("Session: %s/%d\n", inet_ntoa(addr), port);

  /* 
   * Open a synchronization layer session.
   * Use 2k buffers for RTP packets, 64 buffers in pool.
   */
  pssn = synopen(addr, port, 2048, 64);
  if (pssn == NULL) {
    fprintf(stderr, "synopen() returned NULL.\n");
    exit(1);
  }

    /* 
     * Open audio device.
     */
  if ((audio = open("/dev/audio", O_WRONLY)) < 0) {
    perror("open(\"/dev/audio\") failed");
    exit(1);
  }
  
  /*
   * Get a handle to the RTP layer session.
   */
  synctl(pssn, SYN_CTL_GETRTPSESSION, (char *) &psn, 0);
  
  while(TRUE) {
    printf("Looking for audio stream stream...\n");
    while(TRUE) {
      
      /*
       * Get list of sources known by RTP layer.
       */
      count = rtpsources(psn, sources, MAX_SOURCES);

      for (found = FALSE, i = 0; i < count; i++) {
	ssrc = sources[i];
	
	/* 
	 * Get the payload type for source ssrc.
	 */
	rtpctl(psn, RTP_CTL_STREAM_GETPT, (char *) &payloadtype, 0, ssrc);
	
	/*
	 * Look up the encoding represented by payloadtype.
	 * Determine if it's a supported encoding.
	 */
	enc = getencoding(payloadtype);
	if (strcmp(enc.en_name, "PCMU") == 0 ||
	    strcmp(enc.en_name, "PCMA") == 0 ||
#ifdef MPEG
	    strcmp(enc.en_name, "MPA") == 0 ||
#endif /* MPEG */
#ifdef SOLARIS
	    strcmp(enc.en_name, "DVI4") == 0 ||
#endif /* SOLARIS */
	    strcmp(enc.en_name, "L16") == 0) {
	  found = TRUE;
	  break;
	}
      }
      if (found == TRUE)
	break;

      /*
       * If no supported stream found,
       * Wait then try again.
       */
      sleep(1);
    }

    printf("Found sender: SSRC = 0x%x Encoding = %s\n", ssrc, enc.en_name);

    /*
     * Set up audio parameters for sample encodings.
     */
    if (enc.en_format == ENC_SAMPLE) {
#ifdef SOLARIS
      if (strcmp(enc.en_name, "PCMU") == 0)
	encoding = AUDIO_ENCODING_ULAW;
      
      if (strcmp(enc.en_name, "L16") == 0)
	encoding = AUDIO_ENCODING_LINEAR;
      
      if (strcmp(enc.en_name, "PCMA") == 0)
	encoding = AUDIO_ENCODING_ALAW;
      
      if (strcmp(enc.en_name, "DVI4") == 0)
	encoding = AUDIO_ENCODING_DVI;
    
      /*
       * Set up audio device.
       */    
      if (ioctl(audio, AUDIO_GETINFO, &audio_info) < 0) {
	perror("ioctl1");
	exit(1);
      }

      audio_info.play.sample_rate = enc.en_clkrt;
      audio_info.play.channels = enc.en_channels;
      audio_info.play.precision = enc.en_unitsz;
      audio_info.play.encoding = encoding;
      
      if (ioctl(audio, AUDIO_SETINFO, &audio_info) < 0) {
	perror("ioctl2");
	fprintf(stderr, "Perhaps %s is not supported by your system.\n",enc.en_name);
	exit(1);
      }
#endif /* SOLARIS */

#ifdef LINUX
      if (strcmp(enc.en_name, "PCMU") == 0)
	encoding = AFMT_MU_LAW;
      
      if (strcmp(enc.en_name, "L16") == 0)
	encoding = AFMT_S16_LE; /* Little Endian signed 16 bit */
      
      if (strcmp(enc.en_name, "PCMA") == 0)
	encoding = AFMT_A_LAW;
      
      if (ioctl(audio, SNDCTL_DSP_SAMPLESIZE, &enc.en_unitsz) < 0 ||
	  ioctl(audio, SNDCTL_DSP_CHANNELS, &enc.en_channels) < 0 ||
	  ioctl(audio, SNDCTL_DSP_SETFMT, &encoding) < 0 ||
	  ioctl(audio, SNDCTL_DSP_SPEED, &enc.en_clkrt) < 0) {
	perror("ioctl2");
	fprintf(stderr, "Perhaps %s is not supported by your system.\n", enc.en_name);
	exit(1);
      }	
#endif /* LINUX */
    }
#ifdef MPEG
    if (strcmp(enc.en_name, "MPA") == 0) {
      /*
       * MPEG does stereo internally,
       * so only 1 channel of interleaved frames.
       */
      fparameters.fp_channels = 1; 
      
      /*
       * Set pointers to the upcall functions.
       */
      fparameters.fp_framealigned = aligned;
      fparameters.fp_dataoffset = dataoffset;
      fparameters.fp_frameduration = frameduration;
      fparameters.fp_framelength = framelength;
      
      /*
       * Turn the stream on.
       */
      synstreamon(pssn, ssrc, SYN_STREAMTYPE_FRAME, enc.en_clkrt, enc.en_clkrt, &fparameters);

#ifdef LINUX
      /*
       * Use more leeway for Linux. Gives better performance.
       */
      leeway = 160000;
      synctl(pssn, SYN_CTL_STREAM_SETLEEWAY, (char *) &leeway, ssrc);
#endif /* LINUX */

      /*
       * Set inactive threshold to minimum.
       */
      rtpctl(psn, RTP_CTL_STREAM_SETINACTTHR, (char *) &one, 0, ssrc);
      
      /*
       * Call plaympeg to read from stream and play audio.
       */
      while(plaympeg(pssn, ssrc, audio) == ERROR);
    }
    else 
#endif /* MPEG */
      {

	/*
	 * Play sample-oriented stream.
	 * Set sample-read parameters and turn
	 * the stream on.
	 */
	parameters.sp_samplesz = enc.en_unitsz;
	parameters.sp_channels = enc.en_channels;
	synstreamon(pssn, ssrc, SYN_STREAMTYPE_SAMPLE, enc.en_clkrt, enc.en_clkrt, ¶meters);
	/*
	 * Set inactive threshold to minimum. 1 cycle.
	 */
	rtpctl(psn, RTP_CTL_STREAM_SETINACTTHR, (char *) &one, 0, ssrc);

#ifdef LINUX
	/*
	 * Use more leeway.
	 */
	leeway = 20000;
	synctl(pssn, SYN_CTL_STREAM_SETLEEWAY, (char *) &leeway, ssrc);
#endif
	
      while(TRUE) {
	rv = synread(pssn, ssrc, &time, &ts, buf, sizeof(buf), &sreadparam);
	if (rv < 0) {
	  printf("Synread returned %d\n", rv);
	  
	  /* 
	   * Loop to top to get another source.
	   */
	  break; 
	}
	
#if __BYTE_ORDER == __LITTLE_ENDIAN || defined(_LITTLE_ENDIAN)
	/*
	 * Convert sample byte ordering if necessary.
	 */
	if (strcmp(enc.en_name, "L16") == 0)
	  for (i = 0; i < rv; i++) 
	    samp16[i] = ntohs(samp16[i]);
#endif /* LITTLE_ENDIAN */

	/*
	 * Output audio to audio device.
	 */
	write(audio, buf, (rv * enc.en_unitsz) / 8);
      }
    }

    /*
     * Reset audio device before playing another stream.
     */
#ifdef SOLARIS
    ioctl(audio, I_FLUSH, FLUSHW);
#endif
#ifdef LINUX
    ioctl(audio, SNDCTL_DSP_RESET);
#endif
  }
}