📄 main.c
字号:
/*------------------------------------------------------------------------- * main.c - main *------------------------------------------------------------------------- */#include <stdio.h>#include <rtp.h>#include <rtcp.h>#include <netinet/in.h>#include <netdb.h>#include <math.h>#include <event.h>#include <syn.h>#include <payload.h>#include <sample.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <unistd.h>#include <arpa/inet.h>#include <util.h>#include <frame.h>#include <sys/ioctl.h>#include <sys/stropts.h>#include "main.h"#ifdef SOLARIS#include <sys/audioio.h>#endif /* SOLARIS */#ifdef LINUX#include <linux/soundcard.h>#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 <addr> <port>\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 }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -