diff options
Diffstat (limited to 'pjmedia')
-rw-r--r-- | pjmedia/build/pjmedia.dsp | 8 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/errno.h | 5 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/port.h | 1 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/rtcp.h | 69 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/sound.h | 87 | ||||
-rw-r--r-- | pjmedia/include/pjmedia/sound_port.h | 165 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/conference.c | 18 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/endpoint.c | 10 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/errno.c | 1 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/nullsound.c | 28 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/pasound.c | 65 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/rtcp.c | 37 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/sound_port.c | 317 | ||||
-rw-r--r-- | pjmedia/src/pjmedia/stream.c | 18 |
14 files changed, 678 insertions, 151 deletions
diff --git a/pjmedia/build/pjmedia.dsp b/pjmedia/build/pjmedia.dsp index a4bbbbb5..a84395a0 100644 --- a/pjmedia/build/pjmedia.dsp +++ b/pjmedia/build/pjmedia.dsp @@ -168,6 +168,10 @@ SOURCE=..\src\pjmedia\silencedet.c # End Source File
# Begin Source File
+SOURCE=..\src\pjmedia\sound_port.c
+# End Source File
+# Begin Source File
+
SOURCE=..\src\pjmedia\stream.c
# End Source File
# End Group
@@ -256,6 +260,10 @@ SOURCE=..\include\pjmedia\sound.h # End Source File
# Begin Source File
+SOURCE=..\include\pjmedia\sound_port.h
+# End Source File
+# Begin Source File
+
SOURCE=..\include\pjmedia\stream.h
# End Source File
# Begin Source File
diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h index 7537744a..3d95c44a 100644 --- a/pjmedia/include/pjmedia/errno.h +++ b/pjmedia/include/pjmedia/errno.h @@ -415,6 +415,11 @@ PJ_BEGIN_DECL * Incompatible bytes per frame */ #define PJMEDIA_ENCBYTES (PJMEDIA_ERRNO_START+165) /* 220165 */ +/** + * @hideinitializer + * Incompatible number of channels + */ +#define PJMEDIA_ENCCHANNEL (PJMEDIA_ERRNO_START+166) /* 220166 */ /************************************************************ diff --git a/pjmedia/include/pjmedia/port.h b/pjmedia/include/pjmedia/port.h index 5437061a..196e7139 100644 --- a/pjmedia/include/pjmedia/port.h +++ b/pjmedia/include/pjmedia/port.h @@ -78,6 +78,7 @@ struct pjmedia_port_info unsigned pt; /**< Payload type (can be dynamic). */ pj_str_t encoding_name; /**< Encoding name. */ unsigned sample_rate; /**< Sampling rate. */ + unsigned channel_count; /**< Number of channels. */ unsigned bits_per_sample; /**< Bits/sample */ unsigned samples_per_frame; /**< No of samples per frame. */ unsigned bytes_per_frame; /**< No of samples per frame. */ diff --git a/pjmedia/include/pjmedia/rtcp.h b/pjmedia/include/pjmedia/rtcp.h index d0873e72..f39c7800 100644 --- a/pjmedia/include/pjmedia/rtcp.h +++ b/pjmedia/include/pjmedia/rtcp.h @@ -39,7 +39,7 @@ PJ_BEGIN_DECL /** * RTCP sender report. */ -struct pj_rtcp_sr +struct pjmedia_rtcp_sr { pj_uint32_t ssrc; /**< SSRC identification. */ pj_uint32_t ntp_sec; /**< NTP time, seconds part. */ @@ -50,14 +50,14 @@ struct pj_rtcp_sr }; /** - * @see pj_rtcp_sr + * @see pjmedia_rtcp_sr */ -typedef struct pj_rtcp_sr pj_rtcp_sr; +typedef struct pjmedia_rtcp_sr pjmedia_rtcp_sr; /** * RTCP receiver report. */ -struct pj_rtcp_rr +struct pjmedia_rtcp_rr { pj_uint32_t ssrc; /**< SSRC identification. */ #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 @@ -78,15 +78,15 @@ struct pj_rtcp_rr }; /** - * @see pj_rtcp_rr + * @see pjmedia_rtcp_rr */ -typedef struct pj_rtcp_rr pj_rtcp_rr; +typedef struct pjmedia_rtcp_rr pjmedia_rtcp_rr; /** * RTCP common header. */ -struct pj_rtcp_common +struct pjmedia_rtcp_common { #if defined(PJ_IS_BIG_ENDIAN) && PJ_IS_BIG_ENDIAN!=0 unsigned version:2; /**< packet type */ @@ -103,48 +103,48 @@ struct pj_rtcp_common }; /** - * @see pj_rtcp_common + * @see pjmedia_rtcp_common */ -typedef struct pj_rtcp_common pj_rtcp_common; +typedef struct pjmedia_rtcp_common pjmedia_rtcp_common; /** * RTCP packet. */ -struct pj_rtcp_pkt +struct pjmedia_rtcp_pkt { - pj_rtcp_common common; /**< Common header. */ - pj_rtcp_sr sr; /**< Sender report. */ - pj_rtcp_rr rr; /**< variable-length list */ + pjmedia_rtcp_common common; /**< Common header. */ + pjmedia_rtcp_sr sr; /**< Sender report. */ + pjmedia_rtcp_rr rr; /**< variable-length list */ }; /** - * @see pj_rtcp_pkt + * @see pjmedia_rtcp_pkt */ -typedef struct pj_rtcp_pkt pj_rtcp_pkt; +typedef struct pjmedia_rtcp_pkt pjmedia_rtcp_pkt; /** * NTP time representation. */ -struct pj_rtcp_ntp_rec +struct pjmedia_rtcp_ntp_rec { pj_uint32_t hi; /**< High order 32-bit part. */ pj_uint32_t lo; /**< Lo order 32-bit part. */ }; /** - * @see pj_rtcp_ntp_rec + * @see pjmedia_rtcp_ntp_rec */ -typedef struct pj_rtcp_ntp_rec pj_rtcp_ntp_rec; +typedef struct pjmedia_rtcp_ntp_rec pjmedia_rtcp_ntp_rec; /** * RTCP session. */ -struct pj_rtcp_session +struct pjmedia_rtcp_session { - pj_rtcp_pkt rtcp_pkt; /**< Cached RTCP packet. */ + pjmedia_rtcp_pkt rtcp_pkt; /**< Cached RTCP packet. */ pjmedia_rtp_seq_session seq_ctrl; /**< RTCP sequence number control. */ @@ -154,16 +154,16 @@ struct pj_rtcp_session pj_int32_t transit; /**< Relative trans time for prev pkt */ pj_uint32_t jitter; /**< Estimated jitter */ - pj_rtcp_ntp_rec rtcp_lsr; /**< NTP ts in last SR received */ - unsigned rtcp_lsr_time; /**< Time when last SR is received. */ - pj_uint32_t peer_ssrc; /**< Peer SSRC */ + pjmedia_rtcp_ntp_rec rtcp_lsr; /**< NTP ts in last SR received */ + unsigned rtcp_lsr_time; /**< Time when last SR is received.*/ + pj_uint32_t peer_ssrc; /**< Peer SSRC */ }; /** - * @see pj_rtcp_session + * @see pjmedia_rtcp_session */ -typedef struct pj_rtcp_session pj_rtcp_session; +typedef struct pjmedia_rtcp_session pjmedia_rtcp_session; /** @@ -172,7 +172,8 @@ typedef struct pj_rtcp_session pj_rtcp_session; * @param session The session * @param ssrc The SSRC used in to identify the session. */ -PJ_DECL(void) pj_rtcp_init( pj_rtcp_session *session, pj_uint32_t ssrc ); +PJ_DECL(void) pjmedia_rtcp_init( pjmedia_rtcp_session *session, + pj_uint32_t ssrc ); /** @@ -180,7 +181,7 @@ PJ_DECL(void) pj_rtcp_init( pj_rtcp_session *session, pj_uint32_t ssrc ); * * @param session The session. */ -PJ_DECL(void) pj_rtcp_fini( pj_rtcp_session *session); +PJ_DECL(void) pjmedia_rtcp_fini( pjmedia_rtcp_session *session); /** @@ -191,8 +192,9 @@ PJ_DECL(void) pj_rtcp_fini( pj_rtcp_session *session); * @param seq The RTP packet sequence number, in host byte order. * @param ts The RTP packet timestamp, in host byte order. */ -PJ_DECL(void) pj_rtcp_rx_rtp( pj_rtcp_session *session, pj_uint16_t seq, - pj_uint32_t ts ); +PJ_DECL(void) pjmedia_rtcp_rx_rtp( pjmedia_rtcp_session *session, + pj_uint16_t seq, + pj_uint32_t ts ); /** @@ -203,7 +205,8 @@ PJ_DECL(void) pj_rtcp_rx_rtp( pj_rtcp_session *session, pj_uint16_t seq, * @param ptsize The payload size of the RTP packet (ie packet minus * RTP header) in bytes. */ -PJ_DECL(void) pj_rtcp_tx_rtp( pj_rtcp_session *session, pj_uint16_t ptsize ); +PJ_DECL(void) pjmedia_rtcp_tx_rtp( pjmedia_rtcp_session *session, + pj_uint16_t ptsize ); /** @@ -215,9 +218,9 @@ PJ_DECL(void) pj_rtcp_tx_rtp( pj_rtcp_session *session, pj_uint16_t ptsize ); * @param len [output] Upon return, it will indicate the size of * the RTCP packet. */ -PJ_DECL(void) pj_rtcp_build_rtcp( pj_rtcp_session *session, - pj_rtcp_pkt **rtcp_pkt, - int *len ); +PJ_DECL(void) pjmedia_rtcp_build_rtcp( pjmedia_rtcp_session *session, + pjmedia_rtcp_pkt **rtcp_pkt, + int *len ); /** diff --git a/pjmedia/include/pjmedia/sound.h b/pjmedia/include/pjmedia/sound.h index 5719c0f9..3d0b444e 100644 --- a/pjmedia/include/pjmedia/sound.h +++ b/pjmedia/include/pjmedia/sound.h @@ -36,18 +36,18 @@ PJ_BEGIN_DECL */ /** Opaque data type for audio stream. */ -typedef struct pj_snd_stream pj_snd_stream; +typedef struct pjmedia_snd_stream pjmedia_snd_stream; /** - * Device information structure returned by #pj_snd_get_dev_info. + * Device information structure returned by #pjmedia_snd_get_dev_info. */ -typedef struct pj_snd_dev_info +typedef struct pjmedia_snd_dev_info { char name[64]; /**< Device name. */ unsigned input_count; /**< Max number of input channels. */ unsigned output_count; /**< Max number of output channels. */ unsigned default_samples_per_sec;/**< Default sampling rate. */ -} pj_snd_dev_info; +} pjmedia_snd_dev_info; /** * This callback is called by player stream when it needs additional data @@ -62,7 +62,7 @@ typedef struct pj_snd_dev_info * * @return Non-zero to stop the stream. */ -typedef pj_status_t (*pj_snd_play_cb)(/* in */ void *user_data, +typedef pj_status_t (*pjmedia_snd_play_cb)(/* in */ void *user_data, /* in */ pj_uint32_t timestamp, /* out */ void *output, /* out */ unsigned size); @@ -78,7 +78,7 @@ typedef pj_status_t (*pj_snd_play_cb)(/* in */ void *user_data, * * @return Non-zero to stop the stream. */ -typedef pj_status_t (*pj_snd_rec_cb)(/* in */ void *user_data, +typedef pj_status_t (*pjmedia_snd_rec_cb)(/* in */ void *user_data, /* in */ pj_uint32_t timestamp, /* in */ const void *input, /* in*/ unsigned size); @@ -90,7 +90,7 @@ typedef pj_status_t (*pj_snd_rec_cb)(/* in */ void *user_data, * * @return Zero on success. */ -PJ_DECL(pj_status_t) pj_snd_init(pj_pool_factory *factory); +PJ_DECL(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory); /** @@ -98,57 +98,72 @@ PJ_DECL(pj_status_t) pj_snd_init(pj_pool_factory *factory); * * @return Number of devices. */ -PJ_DECL(int) pj_snd_get_dev_count(void); +PJ_DECL(int) pjmedia_snd_get_dev_count(void); /** * Get device info. * * @param index The index of the device, which should be in the range - * from zero to #pj_snd_get_dev_count - 1. + * from zero to #pjmedia_snd_get_dev_count - 1. */ -PJ_DECL(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index); +PJ_DECL(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index); /** * Create a new audio stream for audio capture purpose. * - * @param index Device index, or -1 to let the library choose the first - * available device, or -2 to use NULL device. - * @param param Stream parameters. - * @param rec_cb Callback to handle captured audio samples. - * @param user_data User data to be associated with the stream. - * - * @return Audio stream, or NULL if failed. - */ -PJ_DECL(pj_status_t) pj_snd_open_recorder( int index, + * @param index Device index, or -1 to let the library choose the + * first available device. + * @param clock_rate Sound device's clock rate to set. + * @param channel_count Set number of channels, 1 for mono, or 2 for + * stereo. The channel count determines the format + * of the frame. + * @param samples_per_frame Number of samples per frame. + * @param bits_per_sample Set the number of bits per sample. The normal + * value for this parameter is 16 bits per sample. + * @param rec_cb Callback to handle captured audio samples. + * @param user_data User data to be associated with the stream. + * @param p_snd_strm Pointer to receive the stream instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_snd_open_recorder( int index, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, - pj_snd_rec_cb rec_cb, + pjmedia_snd_rec_cb rec_cb, void *user_data, - pj_snd_stream **p_snd_strm); + pjmedia_snd_stream **p_snd_strm); /** * Create a new audio stream for playing audio samples. * - * @param index Device index, or -1 to let the library choose the first - * available device, or -2 to use NULL device. - * @param param Stream parameters. - * @param play_cb Callback to supply audio samples. - * @param user_data User data to be associated with the stream. - * - * @return Audio stream, or NULL if failed. - */ -PJ_DECL(pj_status_t) pj_snd_open_player( int index, + * @param index Device index, or -1 to let the library choose the + * first available device. + * @param clock_rate Sound device's clock rate to set. + * @param channel_count Set number of channels, 1 for mono, or 2 for + * stereo. The channel count determines the format + * of the frame. + * @param samples_per_frame Number of samples per frame. + * @param bits_per_sample Set the number of bits per sample. The normal + * value for this parameter is 16 bits per sample. + * @param play_cb Callback to be called when the sound player needs + * more audio samples to play. + * @param user_data User data to be associated with the stream. + * @param p_snd_strm Pointer to receive the stream instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_snd_open_player( int index, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, - pj_snd_play_cb play_cb, + pjmedia_snd_play_cb play_cb, void *user_data, - pj_snd_stream **p_snd_strm ); + pjmedia_snd_stream **p_snd_strm ); /** * Start the stream. @@ -157,7 +172,7 @@ PJ_DECL(pj_status_t) pj_snd_open_player( int index, * * @return Zero on success. */ -PJ_DECL(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream); +PJ_DECL(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream); /** * Stop the stream. @@ -166,7 +181,7 @@ PJ_DECL(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream); * * @return Zero on success. */ -PJ_DECL(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream); +PJ_DECL(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream); /** * Destroy the stream. @@ -175,14 +190,14 @@ PJ_DECL(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream); * * @return Zero on success. */ -PJ_DECL(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream); +PJ_DECL(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream); /** * Deinitialize sound library. * * @return Zero on success. */ -PJ_DECL(pj_status_t) pj_snd_deinit(void); +PJ_DECL(pj_status_t) pjmedia_snd_deinit(void); diff --git a/pjmedia/include/pjmedia/sound_port.h b/pjmedia/include/pjmedia/sound_port.h new file mode 100644 index 00000000..c7d1153d --- /dev/null +++ b/pjmedia/include/pjmedia/sound_port.h @@ -0,0 +1,165 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __PJMEDIA_SOUND_PORT_H__ +#define __PJMEDIA_SOUND_PORT_H__ + +/** + * @file sound_port.h + * @brief Media port connection abstraction to sound device. + */ +#include <pjmedia/sound.h> +#include <pjmedia/port.h> + +PJ_BEGIN_DECL + +/** + * @defgroup PJMED_SND_PORT Media Port Connection Abstraction to Sound Device + * @ingroup PJMEDIA + * @{ + */ + +/** + * This opaque type describes sound device port connection. + * Sound device port is not a media port, but it is used to connect media + * port to the sound device. + */ +typedef struct pjmedia_snd_port pjmedia_snd_port; + +/** + * Create sound device port for capturing audio streams from the sound device + * with the specified parameters. + * + * @param pool Pool to allocate sound port structure. + * @param index Device index, or -1 to let the library choose the + * first available device. + * @param clock_rate Sound device's clock rate to set. + * @param channel_count Set number of channels, 1 for mono, or 2 for + * stereo. The channel count determines the format + * of the frame. + * @param samples_per_frame Number of samples per frame. + * @param bits_per_sample Set the number of bits per sample. The normal + * value for this parameter is 16 bits per sample. + * @param options Options flag, currently must be zero. + * @param p_port Pointer to receive the sound device port instance. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_snd_port_create_rec(pj_pool_t *pool, + int index, + unsigned clock_rate, + unsigned channel_count, + unsigned samples_per_frame, + unsigned bits_per_sample, + unsigned options, + pjmedia_snd_port **p_port); + +/** + * Create sound device port for playing audio streams with the specified + * parameters. + * + * @param pool Pool to allocate sound port structure. + * @param index Device index, or -1 to let the library choose the + * first available device. + * @param clock_rate Sound device's clock rate to set. + * @param channel_count Set number of channels, 1 for mono, or 2 for + * stereo. The channel count determines the format + * of the frame. + * @param samples_per_frame Number of samples per frame. + * @param bits_per_sample Set the number of bits per sample. The normal + * value for this parameter is 16 bits per sample. + * @param options Options flag, currently must be zero. + * @param p_port Pointer to receive the sound device port instance. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_snd_port_create_player(pj_pool_t *pool, + int index, + unsigned clock_rate, + unsigned channel_count, + unsigned samples_per_frame, + unsigned bits_per_sample, + unsigned options, + pjmedia_snd_port **p_port); + + +/** + * Destroy sound device port. + * + * @param snd_port The sound device port. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port); + + +/** + * Connect a port to the sound device port. If the sound device port is a + * sound recorder device, then this will start periodic function call to + * the port's put_frame() function. If the sound device is a sound player + * device, then this will start periodic function call to the port's + * get_frame() function. + * + * For this version of PJMEDIA, the media port MUST have the same audio + * settings as the sound device port, or otherwise the connection will + * fail. This means the port MUST have the same clock_rate, channel count, + * samples per frame, and bits per sample as the sound device port. + * + * @param snd_port The sound device port. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_snd_port_connect(pjmedia_snd_port *snd_port, + pjmedia_port *port); + + +/** + * Retrieve the port instance currently attached to the sound port, if any. + * + * @param snd_port The sound device port. + * + * @return The port instance currently attached to the + * sound device port, or NULL if there is no port + * currently attached to the sound device port. + */ +PJ_DECL(pjmedia_port*) pjmedia_snd_port_get_port(pjmedia_snd_port *snd_port); + + +/** + * Disconnect currently attached port from the sound device port. + * + * @param snd_port The sound device port. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_snd_port_disconnect(pjmedia_snd_port *snd_port); + + +/** + * @} + */ + +PJ_END_DECL + + +#endif /* __PJMEDIA_SOUND_PORT_H__ */ + diff --git a/pjmedia/src/pjmedia/conference.c b/pjmedia/src/pjmedia/conference.c index 3dbe7c5a..4c4eba6f 100644 --- a/pjmedia/src/pjmedia/conference.c +++ b/pjmedia/src/pjmedia/conference.c @@ -131,8 +131,8 @@ struct pjmedia_conf unsigned max_ports; /**< Maximum ports. */ unsigned port_cnt; /**< Current number of ports. */ unsigned connect_cnt; /**< Total number of connections */ - pj_snd_stream *snd_rec; /**< Sound recorder stream. */ - pj_snd_stream *snd_player; /**< Sound player stream. */ + pjmedia_snd_stream *snd_rec; /**< Sound recorder stream. */ + pjmedia_snd_stream *snd_player; /**< Sound player stream. */ pj_mutex_t *mutex; /**< Conference mutex. */ struct conf_port **ports; /**< Array of ports. */ pj_uint16_t *uns_buf; /**< Buf for unsigned conversion */ @@ -382,7 +382,7 @@ static pj_status_t create_sound( pjmedia_conf *conf ) /* Open recorder only if mic is not disabled. */ if ((conf->options & PJMEDIA_CONF_NO_MIC) == 0) { - status = pj_snd_open_recorder(-1, conf->clock_rate, 1, + status = pjmedia_snd_open_recorder(-1, conf->clock_rate, 1, conf->samples_per_frame, conf->bits_per_sample, &rec_cb, conf, &conf->snd_rec); @@ -393,13 +393,13 @@ static pj_status_t create_sound( pjmedia_conf *conf ) } /* Open player */ - status = pj_snd_open_player(-1, conf->clock_rate, 1, + status = pjmedia_snd_open_player(-1, conf->clock_rate, 1, conf->samples_per_frame, conf->bits_per_sample, &play_cb, conf, &conf->snd_player); if (status != PJ_SUCCESS) { if (conf->snd_rec) { - pj_snd_stream_close(conf->snd_rec); + pjmedia_snd_stream_close(conf->snd_rec); conf->snd_rec = NULL; } conf->snd_player = NULL; @@ -415,11 +415,11 @@ static pj_status_t create_sound( pjmedia_conf *conf ) static pj_status_t destroy_sound( pjmedia_conf *conf ) { if (conf->snd_rec) { - pj_snd_stream_close(conf->snd_rec); + pjmedia_snd_stream_close(conf->snd_rec); conf->snd_rec = NULL; } if (conf->snd_player) { - pj_snd_stream_close(conf->snd_player); + pjmedia_snd_stream_close(conf->snd_player); conf->snd_player = NULL; } return PJ_SUCCESS; @@ -441,14 +441,14 @@ static pj_status_t resume_sound( pjmedia_conf *conf ) /* Start recorder. */ if (conf->snd_rec) { - status = pj_snd_stream_start(conf->snd_rec); + status = pjmedia_snd_stream_start(conf->snd_rec); if (status != PJ_SUCCESS) goto on_error; } /* Start player. */ if (conf->snd_player) { - status = pj_snd_stream_start(conf->snd_player); + status = pjmedia_snd_stream_start(conf->snd_player); if (status != PJ_SUCCESS) goto on_error; } diff --git a/pjmedia/src/pjmedia/endpoint.c b/pjmedia/src/pjmedia/endpoint.c index 99671017..71217b61 100644 --- a/pjmedia/src/pjmedia/endpoint.c +++ b/pjmedia/src/pjmedia/endpoint.c @@ -106,12 +106,12 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf, endpt->pf = pf; /* Sound */ - pj_snd_init(pf); + pjmedia_snd_init(pf); /* Init codec manager. */ status = pjmedia_codec_mgr_init(&endpt->codec_mgr); if (status != PJ_SUCCESS) { - pj_snd_deinit(); + pjmedia_snd_deinit(); goto on_error; } @@ -122,13 +122,13 @@ PJ_DEF(pj_status_t) pjmedia_endpt_create(pj_pool_factory *pf, status = g711_init_factory (factory, endpt->pool); if (status != PJ_SUCCESS) { - pj_snd_deinit(); + pjmedia_snd_deinit(); goto on_error; } status = pjmedia_codec_mgr_register_factory (&endpt->codec_mgr, factory); if (status != PJ_SUCCESS) { - pj_snd_deinit(); + pjmedia_snd_deinit(); goto on_error; } #endif @@ -158,7 +158,7 @@ PJ_DEF(pj_status_t) pjmedia_endpt_destroy (pjmedia_endpt *endpt) endpt->pf = NULL; - pj_snd_deinit(); + pjmedia_snd_deinit(); pj_pool_release (endpt->pool); return PJ_SUCCESS; diff --git a/pjmedia/src/pjmedia/errno.c b/pjmedia/src/pjmedia/errno.c index b9886796..e6eeccdf 100644 --- a/pjmedia/src/pjmedia/errno.c +++ b/pjmedia/src/pjmedia/errno.c @@ -113,6 +113,7 @@ static const struct { PJMEDIA_ENCTYPE, "Media ports have incompatible media type" }, { PJMEDIA_ENCBITS, "Media ports have incompatible bits per sample" }, { PJMEDIA_ENCBYTES, "Media ports have incompatible bytes per frame" }, + { PJMEDIA_ENCCHANNEL, "Media ports have incompatible number of channels" }, /* Media file errors: */ { PJMEDIA_ENOTVALIDWAVE, "Not a valid WAVE file" }, diff --git a/pjmedia/src/pjmedia/nullsound.c b/pjmedia/src/pjmedia/nullsound.c index ff4e92e7..9d454c08 100644 --- a/pjmedia/src/pjmedia/nullsound.c +++ b/pjmedia/src/pjmedia/nullsound.c @@ -21,7 +21,7 @@ #if defined(PJMEDIA_HAS_NULL_SOUND) && PJMEDIA_HAS_NULL_SOUND!=0 -static pj_snd_dev_info null_info = +static pjmedia_snd_dev_info null_info = { "Null Device", 1, @@ -30,31 +30,31 @@ static pj_snd_dev_info null_info = }; -PJ_DEF(pj_status_t) pj_snd_init(pj_pool_factory *factory) +PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory) { PJ_UNUSED_ARG(factory); return PJ_SUCCESS; } -PJ_DEF(int) pj_snd_get_dev_count(void) +PJ_DEF(int) pjmedia_snd_get_dev_count(void) { return 1; } -PJ_DEF(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index) +PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index) { PJ_ASSERT_RETURN(index==0, NULL); return &null_info; } -PJ_DEF(pj_status_t) pj_snd_open_recorder( int index, +PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, - pj_snd_rec_cb rec_cb, + pjmedia_snd_rec_cb rec_cb, void *user_data, - pj_snd_stream **p_snd_strm) + pjmedia_snd_stream **p_snd_strm) { PJ_UNUSED_ARG(index); PJ_UNUSED_ARG(clock_rate); @@ -69,14 +69,14 @@ PJ_DEF(pj_status_t) pj_snd_open_recorder( int index, return PJ_SUCCESS; } -PJ_DEF(pj_status_t) pj_snd_open_player( int index, +PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, - pj_snd_play_cb play_cb, + pjmedia_snd_play_cb play_cb, void *user_data, - pj_snd_stream **p_snd_strm ) + pjmedia_snd_stream **p_snd_strm ) { PJ_UNUSED_ARG(index); PJ_UNUSED_ARG(clock_rate); @@ -91,25 +91,25 @@ PJ_DEF(pj_status_t) pj_snd_open_player( int index, return PJ_SUCCESS; } -PJ_DEF(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream) +PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream) { PJ_UNUSED_ARG(stream); return PJ_SUCCESS; } -PJ_DEF(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream) +PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream) { PJ_UNUSED_ARG(stream); return PJ_SUCCESS; } -PJ_DEF(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream) +PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream) { PJ_UNUSED_ARG(stream); return PJ_SUCCESS; } -PJ_DEF(pj_status_t) pj_snd_deinit(void) +PJ_DEF(pj_status_t) pjmedia_snd_deinit(void) { return PJ_SUCCESS; } diff --git a/pjmedia/src/pjmedia/pasound.c b/pjmedia/src/pjmedia/pasound.c index 76b8d1bc..ffac434c 100644 --- a/pjmedia/src/pjmedia/pasound.c +++ b/pjmedia/src/pjmedia/pasound.c @@ -32,7 +32,7 @@ static struct snd_mgr pj_pool_factory *factory; } snd_mgr; -struct pj_snd_stream +struct pjmedia_snd_stream { pj_pool_t *pool; pj_str_t name; @@ -45,8 +45,8 @@ struct pj_snd_stream pj_uint32_t underflow; pj_uint32_t overflow; void *user_data; - pj_snd_rec_cb rec_cb; - pj_snd_play_cb play_cb; + pjmedia_snd_rec_cb rec_cb; + pjmedia_snd_play_cb play_cb; pj_bool_t quit_flag; pj_bool_t thread_has_exited; pj_bool_t thread_initialized; @@ -62,7 +62,7 @@ static int PaRecorderCallback(const void *input, PaStreamCallbackFlags statusFlags, void *userData ) { - pj_snd_stream *stream = userData; + pjmedia_snd_stream *stream = userData; pj_status_t status; PJ_UNUSED_ARG(output); @@ -102,7 +102,7 @@ static int PaPlayerCallback( const void *input, PaStreamCallbackFlags statusFlags, void *userData ) { - pj_snd_stream *stream = userData; + pjmedia_snd_stream *stream = userData; pj_status_t status; unsigned size = frameCount * stream->bytes_per_sample; @@ -140,7 +140,7 @@ on_break: /* * Init sound library. */ -PJ_DEF(pj_status_t) pj_snd_init(pj_pool_factory *factory) +PJ_DEF(pj_status_t) pjmedia_snd_init(pj_pool_factory *factory) { int err; @@ -151,16 +151,16 @@ PJ_DEF(pj_status_t) pj_snd_init(pj_pool_factory *factory) PJ_LOG(4,(THIS_FILE, "PortAudio host api count=%d", Pa_GetHostApiCount())); PJ_LOG(4,(THIS_FILE, "Sound device count=%d", - pj_snd_get_dev_count())); + pjmedia_snd_get_dev_count())); - return err; + return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; } /* * Get device count. */ -PJ_DEF(int) pj_snd_get_dev_count(void) +PJ_DEF(int) pjmedia_snd_get_dev_count(void) { return Pa_GetDeviceCount(); } @@ -169,9 +169,9 @@ PJ_DEF(int) pj_snd_get_dev_count(void) /* * Get device info. */ -PJ_DEF(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index) +PJ_DEF(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index) { - static pj_snd_dev_info info; + static pjmedia_snd_dev_info info; const PaDeviceInfo *pa_info; pa_info = Pa_GetDeviceInfo(index); @@ -192,17 +192,17 @@ PJ_DEF(const pj_snd_dev_info*) pj_snd_get_dev_info(unsigned index) /* * Open stream. */ -PJ_DEF(pj_status_t) pj_snd_open_recorder( int index, +PJ_DEF(pj_status_t) pjmedia_snd_open_recorder( int index, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, - pj_snd_rec_cb rec_cb, + pjmedia_snd_rec_cb rec_cb, void *user_data, - pj_snd_stream **p_snd_strm) + pjmedia_snd_stream **p_snd_strm) { pj_pool_t *pool; - pj_snd_stream *stream; + pjmedia_snd_stream *stream; PaStreamParameters inputParam; int sampleFormat; const PaDeviceInfo *paDevInfo = NULL; @@ -277,17 +277,17 @@ PJ_DEF(pj_status_t) pj_snd_open_recorder( int index, } -PJ_DEF(pj_status_t) pj_snd_open_player( int index, +PJ_DEF(pj_status_t) pjmedia_snd_open_player( int index, unsigned clock_rate, unsigned channel_count, unsigned samples_per_frame, unsigned bits_per_sample, - pj_snd_play_cb play_cb, + pjmedia_snd_play_cb play_cb, void *user_data, - pj_snd_stream **p_snd_strm) + pjmedia_snd_stream **p_snd_strm) { pj_pool_t *pool; - pj_snd_stream *stream; + pjmedia_snd_stream *stream; PaStreamParameters outputParam; int sampleFormat; const PaDeviceInfo *paDevInfo = NULL; @@ -366,23 +366,23 @@ PJ_DEF(pj_status_t) pj_snd_open_player( int index, /* * Start stream. */ -PJ_DEF(pj_status_t) pj_snd_stream_start(pj_snd_stream *stream) +PJ_DEF(pj_status_t) pjmedia_snd_stream_start(pjmedia_snd_stream *stream) { - pj_status_t status; + pj_status_t err; PJ_LOG(5,(THIS_FILE, "Starting %s stream..", stream->name.ptr)); - status = Pa_StartStream(stream->stream); + err = Pa_StartStream(stream->stream); - PJ_LOG(5,(THIS_FILE, "Done, status=%d", status)); + PJ_LOG(5,(THIS_FILE, "Done, status=%d", err)); - return status; + return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; } /* * Stop stream. */ -PJ_DEF(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream) +PJ_DEF(pj_status_t) pjmedia_snd_stream_stop(pjmedia_snd_stream *stream) { int i, err; @@ -398,13 +398,13 @@ PJ_DEF(pj_status_t) pj_snd_stream_stop(pj_snd_stream *stream) PJ_LOG(5,(THIS_FILE, "Done, status=%d", err)); - return err; + return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; } /* * Destroy stream. */ -PJ_DEF(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream) +PJ_DEF(pj_status_t) pjmedia_snd_stream_close(pjmedia_snd_stream *stream) { int i, err; const PaDeviceInfo *paDevInfo; @@ -423,17 +423,22 @@ PJ_DEF(pj_status_t) pj_snd_stream_close(pj_snd_stream *stream) err = Pa_CloseStream(stream->stream); pj_pool_release(stream->pool); - return err; + + return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; } /* * Deinitialize sound library. */ -PJ_DEF(pj_status_t) pj_snd_deinit(void) +PJ_DEF(pj_status_t) pjmedia_snd_deinit(void) { + int err; + PJ_LOG(4,(THIS_FILE, "PortAudio sound library shutting down..")); - return Pa_Terminate(); + err = Pa_Terminate(); + + return err ? PJMEDIA_ERRNO_FROM_PORTAUDIO(err) : PJ_SUCCESS; } diff --git a/pjmedia/src/pjmedia/rtcp.c b/pjmedia/src/pjmedia/rtcp.c index e43b8863..e9af1faa 100644 --- a/pjmedia/src/pjmedia/rtcp.c +++ b/pjmedia/src/pjmedia/rtcp.c @@ -31,7 +31,7 @@ /* * Get NTP time. */ -static void rtcp_get_ntp_time(struct pj_rtcp_ntp_rec *ntp) +static void rtcp_get_ntp_time(struct pjmedia_rtcp_ntp_rec *ntp) { pj_time_val tv; @@ -44,11 +44,12 @@ static void rtcp_get_ntp_time(struct pj_rtcp_ntp_rec *ntp) } -PJ_DEF(void) pj_rtcp_init(pj_rtcp_session *s, pj_uint32_t ssrc) +PJ_DEF(void) pjmedia_rtcp_init(pjmedia_rtcp_session *s, + pj_uint32_t ssrc) { - pj_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; + pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; - pj_memset(rtcp_pkt, 0, sizeof(pj_rtcp_pkt)); + pj_memset(rtcp_pkt, 0, sizeof(pjmedia_rtcp_pkt)); /* Init time */ s->rtcp_lsr.hi = s->rtcp_lsr.lo = 0; @@ -66,13 +67,13 @@ PJ_DEF(void) pj_rtcp_init(pj_rtcp_session *s, pj_uint32_t ssrc) /* RR will be initialized on receipt of the first RTP packet. */ } -PJ_DEF(void) pj_rtcp_fini(pj_rtcp_session *session) +PJ_DEF(void) pjmedia_rtcp_fini(pjmedia_rtcp_session *session) { /* Nothing to do. */ PJ_UNUSED_ARG(session); } -static void rtcp_init_seq(pj_rtcp_session *s, pj_uint16_t seq) +static void rtcp_init_seq(pjmedia_rtcp_session *s, pj_uint16_t seq) { s->received = 0; s->expected_prior = 0; @@ -83,7 +84,9 @@ static void rtcp_init_seq(pj_rtcp_session *s, pj_uint16_t seq) pjmedia_rtp_seq_restart(&s->seq_ctrl, seq); } -PJ_DEF(void) pj_rtcp_rx_rtp(pj_rtcp_session *s, pj_uint16_t seq, pj_uint32_t rtp_ts) +PJ_DEF(void) pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *s, + pj_uint16_t seq, + pj_uint32_t rtp_ts) { pj_uint32_t arrival; pj_int32_t transit; @@ -129,19 +132,21 @@ PJ_DEF(void) pj_rtcp_rx_rtp(pj_rtcp_session *s, pj_uint16_t seq, pj_uint32_t rtp } } -PJ_DEF(void) pj_rtcp_tx_rtp(pj_rtcp_session *s, pj_uint16_t bytes_payload_size) +PJ_DEF(void) pjmedia_rtcp_tx_rtp(pjmedia_rtcp_session *s, + pj_uint16_t bytes_payload_size) { - pj_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; + pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; rtcp_pkt->sr.sender_pcount = pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_pcount) + 1); rtcp_pkt->sr.sender_bcount = pj_htonl( pj_ntohl(rtcp_pkt->sr.sender_bcount) + bytes_payload_size ); } -static void rtcp_build_rtcp(pj_rtcp_session *s, pj_uint32_t receiver_ssrc) +static void rtcp_build_rtcp(pjmedia_rtcp_session *s, + pj_uint32_t receiver_ssrc) { pj_uint32_t expected; pj_uint32_t u32; pj_uint32_t expected_interval, received_interval, lost_interval; - pj_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; + pjmedia_rtcp_pkt *rtcp_pkt = &s->rtcp_pkt; /* SSRC and last_seq */ rtcp_pkt->rr.ssrc = pj_htonl(receiver_ssrc); @@ -175,10 +180,12 @@ static void rtcp_build_rtcp(pj_rtcp_session *s, pj_uint32_t receiver_ssrc) } } -PJ_DEF(void) pj_rtcp_build_rtcp(pj_rtcp_session *session, pj_rtcp_pkt **ret_p_pkt, int *len) +PJ_DEF(void) pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *session, + pjmedia_rtcp_pkt **ret_p_pkt, + int *len) { - pj_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt; - pj_rtcp_ntp_rec ntp; + pjmedia_rtcp_pkt *rtcp_pkt = &session->rtcp_pkt; + pjmedia_rtcp_ntp_rec ntp; pj_time_val now; rtcp_build_rtcp(session, session->peer_ssrc); @@ -213,6 +220,6 @@ PJ_DEF(void) pj_rtcp_build_rtcp(pj_rtcp_session *session, pj_rtcp_pkt **ret_p_pk /* Return pointer. */ *ret_p_pkt = rtcp_pkt; - *len = sizeof(pj_rtcp_pkt); + *len = sizeof(pjmedia_rtcp_pkt); } diff --git a/pjmedia/src/pjmedia/sound_port.c b/pjmedia/src/pjmedia/sound_port.c new file mode 100644 index 00000000..f3e285a2 --- /dev/null +++ b/pjmedia/src/pjmedia/sound_port.c @@ -0,0 +1,317 @@ +/* $Id$ */ +/* + * Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <pjmedia/sound_port.h> +#include <pjmedia/errno.h> +#include <pj/assert.h> +#include <pj/string.h> /* pj_memset() */ + +struct pjmedia_snd_port +{ + int snd_index; + pjmedia_snd_stream *snd_stream; + pjmedia_dir dir; + pjmedia_port *port; + + unsigned clock_rate; + unsigned channel_count; + unsigned samples_per_frame; + unsigned bits_per_sample; +}; + +/* + * The callback called by sound player when it needs more samples to be + * played. + */ +static pj_status_t play_cb(/* in */ void *user_data, + /* in */ pj_uint32_t timestamp, + /* out */ void *output, + /* out */ unsigned size) +{ + pjmedia_snd_port *snd_port = user_data; + pjmedia_port *port; + pjmedia_frame frame; + pj_status_t status; + + /* We're risking accessing the port without holding any mutex. + * It's possible that port is disconnected then destroyed while + * we're trying to access it. + * But in the name of performance, we'll try this approach until + * someone complains when it crashes. + */ + port = snd_port->port; + if (port == NULL) + goto no_frame; + + frame.buf = output; + frame.size = size; + frame.timestamp.u32.lo = timestamp; + + status = pjmedia_port_get_frame(port, &frame); + if (status != PJ_SUCCESS) + goto no_frame; + + if (frame.type != PJMEDIA_FRAME_TYPE_AUDIO) + goto no_frame; + + return PJ_SUCCESS; + +no_frame: + pj_memset(output, 0, size); + return PJ_SUCCESS; +} + + +/* + * The callback called by sound recorder when it has finished capturing a + * frame. + */ +static pj_status_t rec_cb(/* in */ void *user_data, + /* in */ pj_uint32_t timestamp, + /* in */ const void *input, + /* in*/ unsigned size) +{ + pjmedia_snd_port *snd_port = user_data; + pjmedia_port *port; + pjmedia_frame frame; + + /* We're risking accessing the port without holding any mutex. + * It's possible that port is disconnected then destroyed while + * we're trying to access it. + * But in the name of performance, we'll try this approach until + * someone complains when it crashes. + */ + port = snd_port->port; + if (port == NULL) + return PJ_SUCCESS; + + frame.buf = (void*)input; + frame.size = size; + frame.type = PJMEDIA_FRAME_TYPE_AUDIO; + frame.timestamp.u32.lo = timestamp; + + pjmedia_port_put_frame(port, &frame); + + return PJ_SUCCESS; +} + +/* + * Start the sound stream. + * This may be called even when the sound stream has already been started. + */ +static pj_status_t start_sound_device( pjmedia_snd_port *snd_port ) +{ + pj_status_t status; + + /* Check if sound has been started. */ + if (snd_port->snd_stream != NULL) + return PJ_SUCCESS; + + /* Open sound stream. */ + if (snd_port->dir == PJMEDIA_DIR_ENCODING) { + status = pjmedia_snd_open_recorder( snd_port->snd_index, + snd_port->clock_rate, + snd_port->channel_count, + snd_port->samples_per_frame, + snd_port->bits_per_sample, + &rec_cb, + snd_port, + &snd_port->snd_stream); + } else { + status = pjmedia_snd_open_player( snd_port->snd_index, + snd_port->clock_rate, + snd_port->channel_count, + snd_port->samples_per_frame, + snd_port->bits_per_sample, + &play_cb, + snd_port, + &snd_port->snd_stream); + } + + if (status != PJ_SUCCESS) + return status; + + /* Start sound stream. */ + status = pjmedia_snd_stream_start(snd_port->snd_stream); + if (status != PJ_SUCCESS) { + pjmedia_snd_stream_close(snd_port->snd_stream); + snd_port->snd_stream = NULL; + return status; + } + + return PJ_SUCCESS; +} + + +/* + * Stop the sound device. + * This may be called even when there's no sound device in the port. + */ +static pj_status_t stop_sound_device( pjmedia_snd_port *snd_port ) +{ + /* Check if we have sound stream device. */ + if (snd_port->snd_stream) { + pjmedia_snd_stream_stop(snd_port->snd_stream); + pjmedia_snd_stream_close(snd_port->snd_stream); + snd_port->snd_stream = NULL; + } + + return PJ_SUCCESS; +} + + +/* + * Create sound recorder port. + */ +PJ_DEF(pj_status_t) pjmedia_snd_port_create_rec( pj_pool_t *pool, + int index, + unsigned clock_rate, + unsigned channel_count, + unsigned samples_per_frame, + unsigned bits_per_sample, + unsigned options, + pjmedia_snd_port **p_port) +{ + pjmedia_snd_port *snd_port; + + PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); + PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); + + snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port)); + PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); + + snd_port->snd_index = index; + snd_port->dir = PJMEDIA_DIR_ENCODING; + snd_port->clock_rate = clock_rate; + snd_port->channel_count = channel_count; + snd_port->samples_per_frame = samples_per_frame; + snd_port->bits_per_sample = bits_per_sample; + + *p_port = snd_port; + + /* Start sound device immediately. + * If there's no port connected, the sound callback will return + * empty signal. + */ + return start_sound_device( snd_port ); +} + + +/* + * Create sound player port. + */ +PJ_DEF(pj_status_t) pjmedia_snd_port_create_player( pj_pool_t *pool, + int index, + unsigned clock_rate, + unsigned channel_count, + unsigned samples_per_frame, + unsigned bits_per_sample, + unsigned options, + pjmedia_snd_port **p_port) +{ + pjmedia_snd_port *snd_port; + + PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL); + PJ_ASSERT_RETURN(options == 0, PJ_EINVAL); + + snd_port = pj_pool_zalloc(pool, sizeof(pjmedia_snd_port)); + PJ_ASSERT_RETURN(snd_port, PJ_ENOMEM); + + snd_port->snd_index = index; + snd_port->dir = PJMEDIA_DIR_DECODING; + snd_port->clock_rate = clock_rate; + snd_port->channel_count = channel_count; + snd_port->samples_per_frame = samples_per_frame; + snd_port->bits_per_sample = bits_per_sample; + + *p_port = snd_port; + + /* Start sound device immediately. + * If there's no port connected, the sound callback will return + * empty signal. + */ + return start_sound_device( snd_port ); +} + + +/* + * Destroy port (also destroys the sound device). + */ +PJ_DEF(pj_status_t) pjmedia_snd_port_destroy(pjmedia_snd_port *snd_port) +{ + PJ_ASSERT_RETURN(snd_port, PJ_EINVAL); + + return stop_sound_device(snd_port); +} + + +/* + * Connect a port. + */ +PJ_DEF(pj_status_t) pjmedia_snd_port_connect( pjmedia_snd_port *snd_port, + pjmedia_port *port) +{ + pjmedia_port_info *pinfo; + + PJ_ASSERT_RETURN(snd_port && port, PJ_EINVAL); + + /* Check that port has the same configuration as the sound device + * port. + */ + pinfo = &port->info; + if (pinfo->sample_rate != snd_port->clock_rate) + return PJMEDIA_ENCCLOCKRATE; + + if (pinfo->samples_per_frame != snd_port->samples_per_frame) + return PJMEDIA_ENCSAMPLESPFRAME; + + if (pinfo->channel_count != snd_port->channel_count) + return PJMEDIA_ENCCHANNEL; + + if (pinfo->bits_per_sample != snd_port->bits_per_sample) + return PJMEDIA_ENCBITS; + + /* Port is okay. */ + snd_port->port = port; + return PJ_SUCCESS; +} + + +/* + * Get the connected port. + */ +PJ_DEF(pjmedia_port*) pjmedia_snd_port_get_port(pjmedia_snd_port *snd_port) +{ + PJ_ASSERT_RETURN(snd_port, NULL); + return snd_port->port; +} + + +/* + * Disconnect port. + */ +PJ_DEF(pj_status_t) pjmedia_snd_port_disconnect(pjmedia_snd_port *snd_port) +{ + PJ_ASSERT_RETURN(snd_port, PJ_EINVAL); + + snd_port->port = NULL; + + return PJ_SUCCESS; +} + + diff --git a/pjmedia/src/pjmedia/stream.c b/pjmedia/src/pjmedia/stream.c index c2624b20..4c06f19f 100644 --- a/pjmedia/src/pjmedia/stream.c +++ b/pjmedia/src/pjmedia/stream.c @@ -99,7 +99,7 @@ struct pjmedia_stream pj_sockaddr_in rem_src_rtp; /**< addr of src pkt from remote*/ unsigned rem_src_cnt; /**< if different, # of pkt rcv */ - pj_rtcp_session rtcp; /**< RTCP for incoming RTP. */ + pjmedia_rtcp_session rtcp; /**< RTCP for incoming RTP. */ pj_bool_t quit_flag; /**< To signal thread exit. */ pj_thread_t *thread; /**< Jitter buffer's thread. */ @@ -520,7 +520,7 @@ static int PJ_THREAD_FUNC jitter_buffer_thread (void*arg) hdr->pt, pj_ntohs(hdr->seq))); continue; } - pj_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); + pjmedia_rtcp_rx_rtp(&stream->rtcp, pj_ntohs(hdr->seq), pj_ntohl(hdr->ts)); /* Update stat */ stream->stat.dec.pkt++; @@ -720,7 +720,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_create( pjmedia_endpt *endpt, /* Init RTCP session: */ - pj_rtcp_init(&stream->rtcp, info->ssrc); + pjmedia_rtcp_init(&stream->rtcp, info->ssrc); /* Create jitter buffer: */ @@ -789,8 +789,8 @@ PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream ) /* if (stream->enc && stream->enc->snd_stream) { - pj_snd_stream_stop(stream->enc->snd_stream); - pj_snd_stream_close(stream->enc->snd_stream); + pjmedia_snd_stream_stop(stream->enc->snd_stream); + pjmedia_snd_stream_close(stream->enc->snd_stream); stream->enc->snd_stream = NULL; } @@ -801,8 +801,8 @@ PJ_DEF(pj_status_t) pjmedia_stream_destroy( pjmedia_stream *stream ) /* if (stream->dec && stream->dec->snd_stream) { - pj_snd_stream_stop(stream->dec->snd_stream); - pj_snd_stream_close(stream->dec->snd_stream); + pjmedia_snd_stream_stop(stream->dec->snd_stream); + pjmedia_snd_stream_close(stream->dec->snd_stream); stream->dec->snd_stream = NULL; } @@ -857,7 +857,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream) if (stream->enc && (stream->dir & PJMEDIA_DIR_ENCODING)) { stream->enc->paused = 0; - //pj_snd_stream_start(stream->enc->snd_stream); + //pjmedia_snd_stream_start(stream->enc->snd_stream); PJ_LOG(4,(THIS_FILE, "Encoder stream started")); } else { PJ_LOG(4,(THIS_FILE, "Encoder stream paused")); @@ -865,7 +865,7 @@ PJ_DEF(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream) if (stream->dec && (stream->dir & PJMEDIA_DIR_DECODING)) { stream->dec->paused = 0; - //pj_snd_stream_start(stream->dec->snd_stream); + //pjmedia_snd_stream_start(stream->dec->snd_stream); PJ_LOG(4,(THIS_FILE, "Decoder stream started")); } else { PJ_LOG(4,(THIS_FILE, "Decoder stream paused")); |