From cd283c8825c9a94400f27735acb1c9385e90ffc8 Mon Sep 17 00:00:00 2001 From: Nanang Izzuddin Date: Tue, 19 Jul 2011 03:42:28 +0000 Subject: Re #1326: Initial code integration from branch 2.0-dev to trunk as "2.0-pre-alpha-svn". git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3664 74dad513-b988-da41-8d7b-12977e46ad98 --- pjmedia/include/pjmedia/avi.h | 202 +++++++ pjmedia/include/pjmedia/avi_stream.h | 170 ++++++ pjmedia/include/pjmedia/circbuf.h | 1 + pjmedia/include/pjmedia/clock.h | 129 +++- pjmedia/include/pjmedia/codec.h | 202 ++++++- pjmedia/include/pjmedia/conference.h | 6 +- pjmedia/include/pjmedia/config.h | 162 +++++ pjmedia/include/pjmedia/converter.h | 322 ++++++++++ pjmedia/include/pjmedia/endpoint.h | 56 ++ pjmedia/include/pjmedia/errno.h | 11 +- pjmedia/include/pjmedia/event.h | 402 +++++++++++++ pjmedia/include/pjmedia/format.h | 748 +++++++++++++++++++++++ pjmedia/include/pjmedia/frame.h | 332 +++++++++++ pjmedia/include/pjmedia/jbuf.h | 113 +++- pjmedia/include/pjmedia/port.h | 205 ++++++- pjmedia/include/pjmedia/sdp.h | 27 +- pjmedia/include/pjmedia/sdp_neg.h | 89 +++ pjmedia/include/pjmedia/signatures.h | 217 +++++++ pjmedia/include/pjmedia/sound_port.h | 14 + pjmedia/include/pjmedia/stream.h | 41 +- pjmedia/include/pjmedia/stream_common.h | 57 ++ pjmedia/include/pjmedia/transport.h | 33 ++ pjmedia/include/pjmedia/transport_ice.h | 24 + pjmedia/include/pjmedia/types.h | 448 +++----------- pjmedia/include/pjmedia/vid_codec.h | 978 +++++++++++++++++++++++++++++++ pjmedia/include/pjmedia/vid_codec_util.h | 158 +++++ pjmedia/include/pjmedia/vid_port.h | 241 ++++++++ pjmedia/include/pjmedia/vid_stream.h | 319 ++++++++++ pjmedia/include/pjmedia/vid_tee.h | 142 +++++ 29 files changed, 5428 insertions(+), 421 deletions(-) create mode 100644 pjmedia/include/pjmedia/avi.h create mode 100644 pjmedia/include/pjmedia/avi_stream.h create mode 100644 pjmedia/include/pjmedia/converter.h create mode 100644 pjmedia/include/pjmedia/event.h create mode 100644 pjmedia/include/pjmedia/format.h create mode 100644 pjmedia/include/pjmedia/frame.h create mode 100644 pjmedia/include/pjmedia/signatures.h create mode 100644 pjmedia/include/pjmedia/stream_common.h create mode 100644 pjmedia/include/pjmedia/vid_codec.h create mode 100644 pjmedia/include/pjmedia/vid_codec_util.h create mode 100644 pjmedia/include/pjmedia/vid_port.h create mode 100644 pjmedia/include/pjmedia/vid_stream.h create mode 100644 pjmedia/include/pjmedia/vid_tee.h (limited to 'pjmedia/include/pjmedia') diff --git a/pjmedia/include/pjmedia/avi.h b/pjmedia/include/pjmedia/avi.h new file mode 100644 index 00000000..685f00eb --- /dev/null +++ b/pjmedia/include/pjmedia/avi.h @@ -0,0 +1,202 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com) + * + * 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_AVI_H__ +#define __PJMEDIA_AVI_H__ + + +/** + * @file avi.h + * @brief AVI file manipulation. + */ + +/** + * @defgroup PJMEDIA_FILE_FORMAT File Formats + * @brief Supported file formats + */ + + +/** + * @defgroup PJMEDIA_AVI AVI Header + * @ingroup PJMEDIA_FILE_FORMAT + * @brief Representation of RIFF/AVI file format + * @{ + * + * This the the low level representation of RIFF/AVI file format. For + * higher abstraction, please see \ref PJMEDIA_FILE_PLAY and + * \ref PJMEDIA_FILE_REC. + */ + + +PJ_BEGIN_DECL + +#define PJMEDIA_AVI_MAX_NUM_STREAMS 4 + +static const char avi_tags[][4] = { + { 'R', 'I', 'F', 'F' }, { 'A', 'V', 'I', ' ' }, + { 'h', 'd', 'r', 'l' }, { 'a', 'v', 'i', 'h' }, + { 's', 't', 'r', 'l' }, { 's', 't', 'r', 'h' }, + { 'a', 'u', 'd', 's' }, { 'v', 'i', 'd', 's' }, + { 's', 't', 'r', 'f' }, { 'm', 'o', 'v', 'i' }, + { 'L', 'I', 'S', 'T' }, { 'J', 'U', 'N', 'K' }, +}; + +typedef enum { + PJMEDIA_AVI_RIFF_TAG = 0, + PJMEDIA_AVI_AVI_TAG, + PJMEDIA_AVI_HDRL_TAG, + PJMEDIA_AVI_AVIH_TAG, + PJMEDIA_AVI_STRL_TAG, + PJMEDIA_AVI_STRH_TAG, + PJMEDIA_AVI_AUDS_TAG, + PJMEDIA_AVI_VIDS_TAG, + PJMEDIA_AVI_STRF_TAG, + PJMEDIA_AVI_MOVI_TAG, + PJMEDIA_AVI_LIST_TAG, + PJMEDIA_AVI_JUNK_TAG, +} pjmedia_avi_tag; + + +/** + * These types describe the simpler/canonical version of an AVI file. + * They do not support the full AVI RIFF format specification. + */ +#pragma pack(2) + +/** This structure describes RIFF AVI file header */ +typedef struct riff_hdr_t { + pj_uint32_t riff; /**< "RIFF" ASCII tag. */ + pj_uint32_t file_len; /**< File length minus 8 bytes */ + pj_uint32_t avi; /**< "AVI" ASCII tag. */ +} riff_hdr_t; + +/** This structure describes avih header */ +typedef struct avih_hdr_t { + pj_uint32_t list_tag; + pj_uint32_t list_sz; + pj_uint32_t hdrl_tag; + pj_uint32_t avih; + pj_uint32_t size; + pj_uint32_t msec_per_frame; /**< microsecs between frames */ + pj_uint32_t max_Bps; + pj_uint32_t pad; + pj_uint32_t flags; + pj_uint32_t tot_frames; + pj_uint32_t init_frames; + pj_uint32_t num_streams; + pj_uint32_t buf_size; + pj_uint32_t width; + pj_uint32_t height; + pj_uint32_t reserved[4]; +} avih_hdr_t; + +/** This structure describes strl header */ +typedef struct strl_hdr_t { + pj_uint32_t list_tag; + pj_uint32_t list_sz; + pj_uint32_t strl_tag; + + pj_uint32_t strh; + pj_uint32_t strh_size; + pj_uint32_t data_type; + pj_uint32_t codec; + pj_uint32_t flags; + pj_uint32_t bogus_priority_language; /**< Do not access this data */ + pj_uint32_t init_frames; + pj_uint32_t scale; + pj_uint32_t rate; + pj_uint32_t start; + pj_uint32_t length; + pj_uint32_t buf_size; + pj_uint32_t quality; + pj_uint32_t sample_size; + pj_uint32_t bogus_frame[2]; /**< Do not access this data */ +} strl_hdr_t; + +typedef struct { + pj_uint32_t strf; + pj_uint32_t strf_size; + pj_uint16_t fmt_tag; /**< 1 for PCM */ + pj_uint16_t nchannels; /**< Number of channels. */ + pj_uint32_t sample_rate; /**< Sampling rate. */ + pj_uint32_t bytes_per_sec; /**< Average bytes per second. */ + pj_uint16_t block_align; /**< nchannels * bits / 8 */ + pj_uint16_t bits_per_sample; /**< Bits per sample. */ + pj_uint16_t extra_size; +} strf_audio_hdr_t; + +/** + * Sizes of strf_audio_hdr_t struct, started by the size (in bytes) of + * 32-bits struct members, alternated with the size of 16-bits members. + */ +static const pj_uint8_t strf_audio_hdr_sizes [] = {8, 4, 8, 6}; + +typedef struct { + pj_uint32_t strf; + pj_uint32_t strf_size; + pj_uint32_t biSize; + pj_int32_t biWidth; + pj_int32_t biHeight; + pj_uint16_t biPlanes; + pj_uint16_t biBitCount; + pj_uint32_t biCompression; + pj_uint32_t biSizeImage; + pj_int32_t biXPelsPerMeter; + pj_int32_t biYPelsPerMeter; + pj_uint32_t biClrUsed; + pj_uint32_t biClrImportant; +} strf_video_hdr_t; + +static const pj_uint8_t strf_video_hdr_sizes [] = {20, 4, 24}; + +struct pjmedia_avi_hdr +{ + riff_hdr_t riff_hdr; + avih_hdr_t avih_hdr; + strl_hdr_t strl_hdr[PJMEDIA_AVI_MAX_NUM_STREAMS]; + union { + strf_audio_hdr_t strf_audio_hdr; + strf_video_hdr_t strf_video_hdr; + } strf_hdr[PJMEDIA_AVI_MAX_NUM_STREAMS]; +}; + +#pragma pack() + +/** + * @see pjmedia_avi_hdr + */ +typedef struct pjmedia_avi_hdr pjmedia_avi_hdr; + +/** + * This structure describes generic RIFF subchunk header. + */ +typedef struct pjmedia_avi_subchunk +{ + pj_uint32_t id; /**< Subchunk ASCII tag. */ + pj_uint32_t len; /**< Length following this field */ +} pjmedia_avi_subchunk; + + +PJ_END_DECL + +/** + * @} + */ + + +#endif /* __PJMEDIA_AVI_H__ */ diff --git a/pjmedia/include/pjmedia/avi_stream.h b/pjmedia/include/pjmedia/avi_stream.h new file mode 100644 index 00000000..9ac68f85 --- /dev/null +++ b/pjmedia/include/pjmedia/avi_stream.h @@ -0,0 +1,170 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com) + * + * 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_AVI_STREAM_H__ +#define __PJMEDIA_AVI_STREAM_H__ + +/** + * @file avi_stream.h + * @brief AVI file player. + */ +#include + + + +PJ_BEGIN_DECL + + +/** + * @defgroup PJMEDIA_FILE_PLAY AVI File Player + * @ingroup PJMEDIA_PORT + * @brief Video and audio playback from AVI file + * @{ + */ + +/** + * AVI file player options. + */ +enum pjmedia_avi_file_player_option +{ + /** + * Tell the file player to return NULL frame when the whole + * file has been played. + */ + PJMEDIA_AVI_FILE_NO_LOOP = 1 +}; + +/** + * AVI stream data type. + */ +typedef pjmedia_port pjmedia_avi_stream; + +/** + * Opaque data type for AVI streams. AVI streams is a collection of + * zero or more AVI stream. + */ +typedef struct pjmedia_avi_streams pjmedia_avi_streams; + +/** + * Create avi streams to play an AVI file. AVI player supports + * reading AVI file with uncompressed video format and + * 16 bit PCM or compressed G.711 A-law/U-law audio format. + * + * @param pool Pool to create the streams. + * @param filename File name to open. + * @param flags Avi streams creation flags. + * @param p_streams Pointer to receive the avi streams instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_avi_player_create_streams(pj_pool_t *pool, + const char *filename, + unsigned flags, + pjmedia_avi_streams **p_streams); + +/** + * Get the number of AVI stream. + * + * @param streams The AVI streams. + * + * @return The number of AVI stream. + */ +PJ_DECL(unsigned) +pjmedia_avi_streams_get_num_streams(pjmedia_avi_streams *streams); + +/** + * Return the idx-th stream of the AVI streams. + * + * @param streams The AVI streams. + * @param idx The stream index. + * + * @return The AVI stream or NULL if it does not exist. + */ +PJ_DECL(pjmedia_avi_stream *) +pjmedia_avi_streams_get_stream(pjmedia_avi_streams *streams, + unsigned idx); + +/** + * Return an AVI stream with a certain media type from the AVI streams. + * + * @param streams The AVI streams. + * @param start_idx The starting index. + * @param media_type The media type of the stream. + * + * @return The AVI stream or NULL if it does not exist. + */ +PJ_DECL(pjmedia_avi_stream *) +pjmedia_avi_streams_get_stream_by_media(pjmedia_avi_streams *streams, + unsigned start_idx, + pjmedia_type media_type); + +/** + * Return the media port of an AVI stream. + * + * @param stream The AVI stream. + * + * @return The media port. + */ +PJ_INLINE(pjmedia_port *) +pjmedia_avi_stream_get_port(pjmedia_avi_stream *stream) +{ + return (pjmedia_port *)stream; +} + +/** + * Get the data length, in bytes. + * + * @param stream The AVI stream. + * + * @return The length of the data, in bytes. Upon error it will + * return negative value. + */ +PJ_DECL(pj_ssize_t) pjmedia_avi_stream_get_len(pjmedia_avi_stream *stream); + + +/** + * Register a callback to be called when the file reading has reached the + * end of file. If the file is set to play repeatedly, then the callback + * will be called multiple times. Note that only one callback can be + * registered for each AVI stream. + * + * @param stream The AVI stream. + * @param user_data User data to be specified in the callback + * @param cb Callback to be called. If the callback returns non- + * PJ_SUCCESS, the playback will stop. Note that if + * application destroys the file port in the callback, + * it must return non-PJ_SUCCESS here. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_avi_stream_set_eof_cb(pjmedia_avi_stream *stream, + void *user_data, + pj_status_t (*cb)(pjmedia_avi_stream *stream, + void *usr_data)); + +/** + * @} + */ + + +PJ_END_DECL + + +#endif /* __PJMEDIA_AVI_STREAM_H__ */ diff --git a/pjmedia/include/pjmedia/circbuf.h b/pjmedia/include/pjmedia/circbuf.h index e891d984..eb3a0740 100644 --- a/pjmedia/include/pjmedia/circbuf.h +++ b/pjmedia/include/pjmedia/circbuf.h @@ -29,6 +29,7 @@ #include #include #include +#include /** * @defgroup PJMED_CIRCBUF Circular Buffer diff --git a/pjmedia/include/pjmedia/clock.h b/pjmedia/include/pjmedia/clock.h index d7dc26e3..dd33a108 100644 --- a/pjmedia/include/pjmedia/clock.h +++ b/pjmedia/include/pjmedia/clock.h @@ -79,6 +79,82 @@ PJ_BEGIN_DECL +/** + * Media clock source. + */ +typedef struct pjmedia_clock_src +{ + pjmedia_type media_type; /**< Media type. */ + unsigned clock_rate; /**< Clock rate. */ + unsigned ptime_usec; /**< Frame interval (in usec). */ + /** + * The timestamp field holds an increasing value in samples and its + * value is expected to be increased by clock_rate samples per second. + */ + pj_timestamp timestamp; + /** + * Timestamp's last update. The last_update field contains a value in + * ticks, and it is expected to be increased by pj_get_timestamp_freq() + * ticks per second. + */ + pj_timestamp last_update; +} pjmedia_clock_src; + +/** + * This is an auxiliary function to initialize the media clock source. + * + * @param clocksrc The clock source to be initialized. + * @param media_type The media type. + * @param clock_rate The clock rate. + * @param ptime_usec Media frame interval (in usec). + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_clock_src_init( pjmedia_clock_src *clocksrc, + pjmedia_type media_type, + unsigned clock_rate, + unsigned ptime_usec ); + +/** + * This function updates the clock source's timestamp. Application should + * use this function instead of updating the timestamp directly since this + * function will also update the last_update field of the clock source. + * + * @param clocksrc The clock source to be updated. + * @param timestamp The new timestamp, can be NULL if the current + * timestamp does not change (in this case it + * will only update the last_update field). + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_clock_src_update( pjmedia_clock_src *clocksrc, + const pj_timestamp *timestamp ); + +/** + * This function gets the clock source's current timestamp. Application + * should use this function instead of accessing the timestamp directly + * since this function will calculate the predicted timestamp for current + * time, based on the values of timestamp, last_update, and clock_rate. + * + * @param clocksrc The clock source. + * @param timestamp Argument to receive the current timestamp + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_clock_src_get_current_timestamp( const pjmedia_clock_src *clocksrc, + pj_timestamp *timestamp); + +/** + * This function gets the clock source's time in msec. + * + * @param clocksrc The clock source. + * + * @return The clock source's time (in msec). + */ +PJ_DECL(pj_uint32_t) +pjmedia_clock_src_get_time_msec( const pjmedia_clock_src *clocksrc ); + /** * Opaque declaration for media clock. @@ -105,6 +181,19 @@ enum pjmedia_clock_options }; +typedef struct pjmedia_clock_param +{ + /** + * The frame interval, in microseconds. + */ + unsigned usec_interval; + /** + * The media clock rate, to determine timestamp + * increment for each call. + */ + unsigned clock_rate; +} pjmedia_clock_param; + /** * Type of media clock callback. * @@ -118,7 +207,12 @@ typedef void pjmedia_clock_callback(const pj_timestamp *ts, /** - * Create media clock. + * Create media clock. This creates a media clock object that will run + * periodically at an interval that is calculated from the audio parameters. + * Once created, application must call #pjmedia_clock_start() to actually + * start the clock. + * + * @see pjmedia_clock_create2() * * @param pool Pool to allocate memory. * @param clock_rate Number of samples per second. @@ -143,6 +237,29 @@ PJ_DECL(pj_status_t) pjmedia_clock_create( pj_pool_t *pool, void *user_data, pjmedia_clock **p_clock); + +/** + * Create media clock. This creates a media clock object that will run + * periodically at the specified interval. Once created, application must + * call #pjmedia_clock_start() to actually start the clock. + * + * @param pool Pool to allocate memory. + * @param param The clock parameter. + * @param options Bitmask of pjmedia_clock_options. + * @param cb Callback to be called for each clock tick. + * @param user_data User data, which will be passed to the callback. + * @param p_clock Pointer to receive the clock instance. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_clock_create2(pj_pool_t *pool, + const pjmedia_clock_param *param, + unsigned options, + pjmedia_clock_callback *cb, + void *user_data, + pjmedia_clock **p_clock); + /** * Start the clock. For clock created with asynchronous flag set to TRUE, * this may start a worker thread for the clock (depending on the @@ -165,6 +282,16 @@ PJ_DECL(pj_status_t) pjmedia_clock_start(pjmedia_clock *clock); PJ_DECL(pj_status_t) pjmedia_clock_stop(pjmedia_clock *clock); +/** + * Modify the clock's parameter. + * + * @param clock The media clock. + * @param param The clock's new parameter. + * @return PJ_SUCCES on success. + */ +PJ_DECL(pj_status_t) pjmedia_clock_modify(pjmedia_clock *clock, + const pjmedia_clock_param *param); + /** * Poll the media clock, and execute the callback when the clock tick has diff --git a/pjmedia/include/pjmedia/codec.h b/pjmedia/include/pjmedia/codec.h index 50f70297..8e2f23bc 100644 --- a/pjmedia/include/pjmedia/codec.h +++ b/pjmedia/include/pjmedia/codec.h @@ -27,6 +27,7 @@ */ #include +#include #include #include @@ -240,8 +241,6 @@ typedef struct pjmedia_codec_info unsigned channel_cnt; /**< Channel count. */ } pjmedia_codec_info; -#define PJMEDIA_CODEC_MAX_FMTP_CNT 8 - /** * Structure of codec specific parameters which contains name=value pairs. * The codec specific parameters are to be used with SDP according to @@ -325,6 +324,9 @@ typedef struct pjmedia_codec_op /** * Initialize codec using the specified attribute. * + * Application should call #pjmedia_codec_init() instead of + * calling this function directly. + * * @param codec The codec instance. * @param pool Pool to use when the codec needs to allocate * some memory. @@ -340,6 +342,9 @@ typedef struct pjmedia_codec_op * and fills in the unspecified values (such as enc_ptime, when * encoder ptime is different than decoder ptime). * + * Application should call #pjmedia_codec_open() instead of + * calling this function directly. + * * @param codec The codec instance. * @param param Codec initialization parameter. * @@ -352,6 +357,9 @@ typedef struct pjmedia_codec_op * Close and shutdown codec, releasing all resources allocated by * this codec, if any. * + * Application should call #pjmedia_codec_close() instead of + * calling this function directly. + * * @param codec The codec instance. * * @return PJ_SUCCESS on success. @@ -367,6 +375,9 @@ typedef struct pjmedia_codec_op * Application can expect changing trivial codec settings such as * changing VAD setting to succeed. * + * Application should call #pjmedia_codec_modify() instead of + * calling this function directly. + * * @param codec The codec instance. * @param param The new codec parameter. * @@ -381,6 +392,9 @@ typedef struct pjmedia_codec_op * have ptime that is equal to basic frame ptime (i.e. the value of * info.frm_ptime in #pjmedia_codec_param). * + * Application should call #pjmedia_codec_parse() instead of + * calling this function directly. + * * @param codec The codec instance * @param pkt The input packet. * @param pkt_size Size of the packet. @@ -405,6 +419,9 @@ typedef struct pjmedia_codec_op * PCM samples MUST have ptime that is multiplication of base frame * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param). * + * Application should call #pjmedia_codec_encode() instead of + * calling this function directly. + * * @param codec The codec instance. * @param input The input frame. * @param out_size The length of buffer in the output frame. @@ -424,6 +441,9 @@ typedef struct pjmedia_codec_op * Application can achieve this by parsing the packet into base * frames before decoding each frame. * + * Application should call #pjmedia_codec_decode() instead of + * calling this function directly. + * * @param codec The codec instance. * @param input The input frame. * @param out_size The length of buffer in the output frame. @@ -439,6 +459,9 @@ typedef struct pjmedia_codec_op /** * Instruct the codec to recover a missing frame. * + * Application should call #pjmedia_codec_recover() instead of + * calling this function directly. + * * @param codec The codec instance. * @param out_size The length of buffer in the output frame. * @param output The output frame where generated signal @@ -554,6 +577,11 @@ typedef struct pjmedia_codec_factory_op pj_status_t (*dealloc_codec)(pjmedia_codec_factory *factory, pjmedia_codec *codec ); + /** + * This callback will be called to deinitialize and destroy this factory. + */ + pj_status_t (*destroy)(void); + } pjmedia_codec_factory_op; @@ -725,10 +753,11 @@ pjmedia_codec_mgr_register_factory( pjmedia_codec_mgr *mgr, /** * Unregister codec factory from the codec manager. This will also * remove all the codecs registered by the codec factory from the - * codec manager's list of supported codecs. + * codec manager's list of supported codecs. This function should + * only be called by the codec implementers and not by application. * - * @param mgr The codec manager instance. Application can get the - * instance by calling #pjmedia_endpt_get_codec_mgr(). + * @param mgr The codec manager instance, use + * #pjmedia_endpt_get_codec_mgr(). * @param factory The codec factory to be unregistered. * * @return PJ_SUCCESS on success. @@ -908,6 +937,169 @@ PJ_DECL(pj_status_t) pjmedia_codec_mgr_dealloc_codec(pjmedia_codec_mgr *mgr, +/** + * Initialize codec using the specified attribute. + * + * @param codec The codec instance. + * @param pool Pool to use when the codec needs to allocate some memory. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_codec_init( pjmedia_codec *codec, + pj_pool_t *pool ) +{ + return (*codec->op->init)(codec, pool); +} + + +/** + * Open the codec and initialize with the specified parameter. + * Upon successful initialization, the codec may modify the parameter + * and fills in the unspecified values (such as enc_ptime, when + * encoder ptime is different than decoder ptime). + * + * @param codec The codec instance. + * @param param Codec initialization parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_codec_open( pjmedia_codec *codec, + pjmedia_codec_param *param ) +{ + return (*codec->op->open)(codec, param); +} + + +/** + * Close and shutdown codec, releasing all resources allocated by + * this codec, if any. + * + * @param codec The codec instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_codec_close( pjmedia_codec *codec ) +{ + return (*codec->op->close)(codec); +} + + +/** + * Modify the codec parameter after the codec is open. + * Note that not all codec parameters can be modified during run-time. + * When the parameter cannot be changed, this function will return + * non-PJ_SUCCESS, and the original parameters will not be changed. + * + * Application can expect changing trivial codec settings such as + * changing VAD setting to succeed. + * + * @param codec The codec instance. + * @param param The new codec parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_codec_modify(pjmedia_codec *codec, + const pjmedia_codec_param *param) +{ + return (*codec->op->modify)(codec, param); +} + + +/** + * Instruct the codec to inspect the specified payload/packet and + * split the packet into individual base frames. Each output frames will + * have ptime that is equal to basic frame ptime (i.e. the value of + * info.frm_ptime in #pjmedia_codec_param). + * + * @param codec The codec instance + * @param pkt The input packet. + * @param pkt_size Size of the packet. + * @param timestamp The timestamp of the first sample in the packet. + * @param frame_cnt On input, specifies the maximum number of frames + * in the array. On output, the codec must fill + * with number of frames detected in the packet. + * @param frames On output, specifies the frames that have been + * detected in the packet. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_codec_parse( pjmedia_codec *codec, + void *pkt, + pj_size_t pkt_size, + const pj_timestamp *timestamp, + unsigned *frame_cnt, + pjmedia_frame frames[] ) +{ + return (*codec->op->parse)(codec, pkt, pkt_size, timestamp, + frame_cnt, frames); +} + + +/** + * Instruct the codec to encode the specified input frame. The input + * PCM samples MUST have ptime that is multiplication of base frame + * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param). + * + * @param codec The codec instance. + * @param input The input frame. + * @param out_size The length of buffer in the output frame. + * @param output The output frame. + * + * @return PJ_SUCCESS on success; + */ +PJ_INLINE(pj_status_t) pjmedia_codec_encode( + pjmedia_codec *codec, + const struct pjmedia_frame *input, + unsigned out_size, + struct pjmedia_frame *output ) +{ + return (*codec->op->encode)(codec, input, out_size, output); +} + + +/** + * Instruct the codec to decode the specified input frame. The input + * frame MUST have ptime that is exactly equal to base frame + * ptime (i.e. the value of info.frm_ptime in #pjmedia_codec_param). + * Application can achieve this by parsing the packet into base + * frames before decoding each frame. + * + * @param codec The codec instance. + * @param input The input frame. + * @param out_size The length of buffer in the output frame. + * @param output The output frame. + * + * @return PJ_SUCCESS on success; + */ +PJ_INLINE(pj_status_t) pjmedia_codec_decode( + pjmedia_codec *codec, + const struct pjmedia_frame *input, + unsigned out_size, + struct pjmedia_frame *output ) +{ + return (*codec->op->decode)(codec, input, out_size, output); +} + + +/** + * Instruct the codec to recover a missing frame. + * + * @param codec The codec instance. + * @param out_size The length of buffer in the output frame. + * @param output The output frame where generated signal + * will be placed. + * + * @return PJ_SUCCESS on success; + */ +PJ_INLINE(pj_status_t) pjmedia_codec_recover( pjmedia_codec *codec, + unsigned out_size, + struct pjmedia_frame *output ) +{ + if (codec->op && codec->op->recover) + return (*codec->op->recover)(codec, out_size, output); + else + return PJ_ENOTSUP; +} /** diff --git a/pjmedia/include/pjmedia/conference.h b/pjmedia/include/pjmedia/conference.h index e6ac6617..649a4d49 100644 --- a/pjmedia/include/pjmedia/conference.h +++ b/pjmedia/include/pjmedia/conference.h @@ -46,14 +46,12 @@ PJ_BEGIN_DECL /** * The conference bridge signature in pjmedia_port_info. */ -#define PJMEDIA_CONF_BRIDGE_SIGNATURE \ - PJMEDIA_PORT_SIGNATURE('C', 'O', 'N', 'F') +#define PJMEDIA_CONF_BRIDGE_SIGNATURE PJMEDIA_SIG_PORT_CONF /** * The audio switchboard signature in pjmedia_port_info. */ -#define PJMEDIA_CONF_SWITCH_SIGNATURE \ - PJMEDIA_PORT_SIGNATURE('A', 'S', 'W', 'I') +#define PJMEDIA_CONF_SWITCH_SIGNATURE PJMEDIA_SIG_PORT_CONF_SWITCH /** diff --git a/pjmedia/include/pjmedia/config.h b/pjmedia/include/pjmedia/config.h index 6b7fc9b4..bbcf2224 100644 --- a/pjmedia/include/pjmedia/config.h +++ b/pjmedia/include/pjmedia/config.h @@ -514,6 +514,15 @@ # define PJMEDIA_STREAM_CHECK_RTP_PT 1 #endif +/** + * Reserve some space for application extra data, e.g: SRTP auth tag, + * in RTP payload, so the total payload length will not exceed the MTU. + */ +#ifndef PJMEDIA_STREAM_RESV_PAYLOAD_LEN +# define PJMEDIA_STREAM_RESV_PAYLOAD_LEN 20 +#endif + + /** * Specify the maximum duration of silence period in the codec, in msec. * This is useful for example to keep NAT binding open in the firewall @@ -567,6 +576,16 @@ #endif +/** + * Maximum number of parameters in SDP fmtp attribute. + * + * Default: 16 + */ +#ifndef PJMEDIA_CODEC_MAX_FMTP_CNT +# define PJMEDIA_CODEC_MAX_FMTP_CNT 16 +#endif + + /** * This specifies the behavior of the SDP negotiator when responding to an * offer, whether it should rather use the codec preference as set by @@ -591,6 +610,15 @@ #endif +/** + * This specifies the maximum number of the customized SDP format + * negotiation callbacks. + */ +#ifndef PJMEDIA_SDP_NEG_MAX_CUSTOM_FMT_NEG_CB +# define PJMEDIA_SDP_NEG_MAX_CUSTOM_FMT_NEG_CB 8 +#endif + + /** * Support for sending and decoding RTCP port in SDP (RFC 3605). * Default is equal to PJMEDIA_ADVERTISE_RTCP setting. @@ -880,6 +908,140 @@ #endif +/* + * .... new stuffs ... + */ + +/* + * Video + */ + +/** + * Top level option to disable video. + */ +#ifndef PJMEDIA_HAS_VIDEO +# define PJMEDIA_HAS_VIDEO 1 +#endif + + +/** + * Specify if FFMPEG is available. The value here will be used as the default + * value for other FFMPEG settings below. + * + * Default: 0 + */ +#ifndef PJMEDIA_HAS_FFMPEG +# define PJMEDIA_HAS_FFMPEG 0 +#endif + +/** + * Specify if FFMPEG libavformat is available. + * + * Default: PJMEDIA_HAS_FFMPEG (or detected by configure) + */ +#ifndef PJMEDIA_HAS_LIBAVFORMAT +# define PJMEDIA_HAS_LIBAVFORMAT PJMEDIA_HAS_FFMPEG +#endif + +/** + * Specify if FFMPEG libavformat is available. + * + * Default: PJMEDIA_HAS_FFMPEG (or detected by configure) + */ +#ifndef PJMEDIA_HAS_LIBAVCODEC +# define PJMEDIA_HAS_LIBAVCODEC PJMEDIA_HAS_FFMPEG +#endif + +/** + * Specify if FFMPEG libavutil is available. + * + * Default: PJMEDIA_HAS_FFMPEG (or detected by configure) + */ +#ifndef PJMEDIA_HAS_LIBAVUTIL +# define PJMEDIA_HAS_LIBAVUTIL PJMEDIA_HAS_FFMPEG +#endif + +/** + * Specify if FFMPEG libswscale is available. + * + * Default: PJMEDIA_HAS_FFMPEG (or detected by configure) + */ +#ifndef PJMEDIA_HAS_LIBSWSCALE +# define PJMEDIA_HAS_LIBSWSCALE PJMEDIA_HAS_FFMPEG +#endif + +/** + * Specify if FFMPEG libavdevice is available. + * + * Default: PJMEDIA_HAS_FFMPEG (or detected by configure) + */ +#ifndef PJMEDIA_HAS_LIBAVDEVICE +# define PJMEDIA_HAS_LIBAVDEVICE PJMEDIA_HAS_FFMPEG +#endif + +/** + * Specify if FFMPEG libavcore is available. + * + * Default: PJMEDIA_HAS_FFMPEG (or detected by configure) + */ +#ifndef PJMEDIA_HAS_LIBAVCORE +# define PJMEDIA_HAS_LIBAVCORE PJMEDIA_HAS_FFMPEG +#endif + +/** + * Maximum video planes. + * + * Default: 4 + */ +#ifndef PJMEDIA_MAX_VIDEO_PLANES +# define PJMEDIA_MAX_VIDEO_PLANES 4 +#endif + +/** + * Maximum number of video formats. + * + * Default: 32 + */ +#ifndef PJMEDIA_MAX_VIDEO_FORMATS +# define PJMEDIA_MAX_VIDEO_FORMATS 32 +#endif + +/** + * Specify the maximum time difference (in ms) for synchronization between + * two medias. If the synchronization media source is ahead of time + * greater than this duration, it is considered to make a very large jump + * and the synchronization will be reset. + * + * Default: 20000 + */ +#ifndef PJMEDIA_CLOCK_SYNC_MAX_SYNC_MSEC +# define PJMEDIA_CLOCK_SYNC_MAX_SYNC_MSEC 20000 +#endif + +/** + * Maximum video frame size. + * Default: 128kB + */ +#ifndef PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE +# define PJMEDIA_MAX_VIDEO_ENC_FRAME_SIZE (1<<17) +#endif + + +/** + * Specify the maximum duration (in ms) for resynchronization. When a media + * is late to another media it is supposed to be synchronized to, it is + * guaranteed to be synchronized again after this duration. While if the + * media is ahead/early by t ms, it is guaranteed to be synchronized after + * t + this duration. This timing only applies if there is no additional + * resynchronization required during the specified duration. + * + * Default: 2000 + */ +#ifndef PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION +# define PJMEDIA_CLOCK_SYNC_MAX_RESYNC_DURATION 2000 +#endif + + /** * @} */ diff --git a/pjmedia/include/pjmedia/converter.h b/pjmedia/include/pjmedia/converter.h new file mode 100644 index 00000000..8a9dd11a --- /dev/null +++ b/pjmedia/include/pjmedia/converter.h @@ -0,0 +1,322 @@ +/* $Id$ */ +/* + * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com) + * + * 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_CONVERTER_H__ +#define __PJMEDIA_CONVERTER_H__ + + +/** + * @file pjmedia/converter.h Format conversion utilities + * @brief Format conversion utilities + */ + +#include +#include +#include +#include + + +/** + * @defgroup PJMEDIA_CONVERTER Format converter + * @ingroup PJMEDIA_FRAME_OP + * @brief Audio and video converter utilities + * @{ + */ + +PJ_BEGIN_DECL + +/** + * This describes conversion parameter. It specifies the source and + * destination formats of the conversion. + */ +typedef struct pjmedia_conversion_param +{ + pjmedia_format src; /**< Source format. */ + pjmedia_format dst; /**< Destination format. */ +} pjmedia_conversion_param; + + +/** Forward declaration of factory operation structure */ +typedef struct pjmedia_converter_factory_op pjmedia_converter_factory_op; + +/** + * Converter priority guides. Converter priority determines which converter + * instance to be used if more than one converters are able to perform the + * requested conversion. Converter implementor can use this value to order + * the preference based on attributes such as quality or performance. Higher + * number indicates higher priority. + */ +typedef enum pjmedia_converter_priority_guide +{ + /** Lowest priority. */ + PJMEDIA_CONVERTER_PRIORITY_LOWEST = 0, + + /** Normal priority. */ + PJMEDIA_CONVERTER_PRIORITY_NORMAL = 15000, + + /** Highest priority. */ + PJMEDIA_CONVERTER_PRIORITY_HIGHEST = 32000 +} pjmedia_converter_priority_guide; + +/** + * Converter factory. The converter factory registers a callback function + * to create converters. + */ +typedef struct pjmedia_converter_factory +{ + /** + * Standard list members. + */ + PJ_DECL_LIST_MEMBER(struct pjmedia_converter_factory); + + /** + * Factory name. + */ + const char *name; + + /** + * Converter priority determines which converter instance to be used if + * more than one converters are able to perform the requested conversion. + * Converter implementor can use this value to order the preference based + * on attributes such as quality or performance. Higher number indicates + * higher priority. The pjmedia_converter_priority_guide enumeration shall + * be used as the base value to set the priority. + */ + int priority; + + /** + * Pointer to factory operation. + */ + pjmedia_converter_factory_op *op; + +} pjmedia_converter_factory; + +/** Forward declaration for converter operation. */ +typedef struct pjmedia_converter_op pjmedia_converter_op; + +/** + * This structure describes a converter instance. + */ +typedef struct pjmedia_converter +{ + /** + * Pointer to converter operation. + */ + pjmedia_converter_op *op; + +} pjmedia_converter; + + +/** + * Converter factory operation. + */ +struct pjmedia_converter_factory_op +{ + /** + * This function creates a converter with the specified conversion format, + * if such format is supported. + * + * @param cf The converter factory. + * @param pool Pool to allocate memory from. + * @param prm Conversion parameter. + * @param p_cv Pointer to hold the created converter instance. + * + * @return PJ_SUCCESS if converter has been created successfully. + */ + pj_status_t (*create_converter)(pjmedia_converter_factory *cf, + pj_pool_t *pool, + const pjmedia_conversion_param *prm, + pjmedia_converter **p_cv); + + /** + * Destroy the factory. + * + * @param cf The converter factory. + */ + void (*destroy_factory)(pjmedia_converter_factory *cf); +}; + +/** + * Converter operation. + */ +struct pjmedia_converter_op +{ + /** + * Convert the buffer in the source frame and save the result in the + * buffer of the destination frame, according to conversion format that + * was specified when the converter was created. + * + * Note that application should use #pjmedia_converter_convert() instead + * of calling this function directly. + * + * @param cv The converter instance. + * @param src_frame The source frame. + * @param dst_frame The destination frame. + * + * @return PJ_SUCCESS if conversion has been performed + * successfully. + */ + pj_status_t (*convert)(pjmedia_converter *cv, + pjmedia_frame *src_frame, + pjmedia_frame *dst_frame); + + /** + * Destroy the converter instance. + * + * Note that application should use #pjmedia_converter_destroy() instead + * of calling this function directly. + * + * @param cv The converter. + */ + void (*destroy)(pjmedia_converter *cv); + +}; + + +/** + * Opaque data type for conversion manager. Typically, the conversion manager + * is a singleton instance, although application may instantiate more than one + * instances of this if required. + */ +typedef struct pjmedia_converter_mgr pjmedia_converter_mgr; + + +/** + * Create a new conversion manager instance. This will also set the pointer + * to the singleton instance if the value is still NULL. + * + * @param pool Pool to allocate memory from. + * @param mgr Pointer to hold the created instance of the + * conversion manager. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_converter_mgr_create(pj_pool_t *pool, + pjmedia_converter_mgr **mgr); + +/** + * Get the singleton instance of the conversion manager. + * + * @return The instance. + */ +PJ_DECL(pjmedia_converter_mgr*) pjmedia_converter_mgr_instance(void); + +/** + * Manually assign a specific video manager instance as the singleton + * instance. Normally this is not needed if only one instance is ever + * going to be created, as the library automatically assign the singleton + * instance. + * + * @param mgr The instance to be used as the singleton instance. + * Application may specify NULL to clear the singleton + * singleton instance. + */ +PJ_DECL(void) pjmedia_converter_mgr_set_instance(pjmedia_converter_mgr *mgr); + +/** + * Destroy a converter manager. If the manager happens to be the singleton + * instance, the singleton instance will be set to NULL. + * + * @param mgr The converter manager. Specify NULL to use + * the singleton instance. + */ +PJ_DECL(void) pjmedia_converter_mgr_destroy(pjmedia_converter_mgr *mgr); + +/** + * Register a converter factory to the converter manager. + * + * @param mgr The converter manager. Specify NULL to use + * the singleton instance. + * @param f The converter factory to be registered. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) +pjmedia_converter_mgr_register_factory(pjmedia_converter_mgr *mgr, + pjmedia_converter_factory *f); + +/** + * Unregister a previously registered converter factory from the converter + * manager. + * + * @param mgr The converter manager. Specify NULL to use + * the singleton instance. + * @param f The converter factory to be unregistered. + * @param call_destroy If this is set to non-zero, the \a destroy_factory() + * callback of the factory will be called while + * unregistering the factory from the manager. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) +pjmedia_converter_mgr_unregister_factory(pjmedia_converter_mgr *mgr, + pjmedia_converter_factory *f, + pj_bool_t call_destroy); + +/** + * Create a converter instance to perform the specified format conversion + * as specified in \a param. + * + * @param mgr The converter manager. Specify NULL to use + * the singleton instance. + * @param pool Pool to allocate the memory from. + * @param param Conversion parameter. + * @param p_cv Pointer to hold the created converter. + * + * @return PJ_SUCCESS if a converter has been created successfully + * or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_converter_create(pjmedia_converter_mgr *mgr, + pj_pool_t *pool, + pjmedia_conversion_param *param, + pjmedia_converter **p_cv); + +/** + * Convert the buffer in the source frame and save the result in the + * buffer of the destination frame, according to conversion format that + * was specified when the converter was created. + * + * @param cv The converter instance. + * @param src_frame The source frame. + * @param dst_frame The destination frame. + * + * @return PJ_SUCCESS if conversion has been performed + * successfully. + */ +PJ_DECL(pj_status_t) pjmedia_converter_convert(pjmedia_converter *cv, + pjmedia_frame *src_frame, + pjmedia_frame *dst_frame); + +/** + * Destroy the converter. + * + * @param cv The converter instance. + */ +PJ_DECL(void) pjmedia_converter_destroy(pjmedia_converter *cv); + + +PJ_END_DECL + +/** + * @} + */ + + +#endif /* __PJMEDIA_CONVERTER_H__ */ + + diff --git a/pjmedia/include/pjmedia/endpoint.h b/pjmedia/include/pjmedia/endpoint.h index 37778b7a..9956b95f 100644 --- a/pjmedia/include/pjmedia/endpoint.h +++ b/pjmedia/include/pjmedia/endpoint.h @@ -39,6 +39,7 @@ #include #include +#include PJ_BEGIN_DECL @@ -179,6 +180,9 @@ PJ_DECL(pjmedia_codec_mgr*) pjmedia_endpt_get_codec_mgr(pjmedia_endpt *endpt); * @param stream_cnt Number of elements in the sock_info array. This * also denotes the maximum number of streams (i.e. * the "m=" lines) that will be created in the SDP. + * By convention, if this value is greater than one, + * the first media will be audio and the remaining + * media is video. * @param sock_info Array of socket transport information. One * transport is needed for each media stream, and * each transport consists of an RTP and RTCP socket @@ -193,6 +197,58 @@ PJ_DECL(pj_status_t) pjmedia_endpt_create_sdp( pjmedia_endpt *endpt, const pjmedia_sock_info sock_info[], pjmedia_sdp_session **p_sdp ); +/** + * Create a "blank" SDP session description. The SDP will contain basic SDP + * fields such as origin, time, and name, but without any media lines. + * + * @param endpt The media endpoint. + * @param pool Pool to allocate memory from. + * @param sess_name Optional SDP session name, or NULL to use default + * value. + * @param origin Address to put in the origin field. + * @param p_sdp Pointer to receive the created SDP session. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_endpt_create_base_sdp(pjmedia_endpt *endpt, + pj_pool_t *pool, + const pj_str_t *sess_name, + const pj_sockaddr *origin, + pjmedia_sdp_session **p_sdp); + +/** + * Create SDP media line for audio media. + * + * @param endpt The media endpoint. + * @param pool Pool to allocate memory from. + * @param si Socket information. + * @param options Option flags, must be zero for now. + * @param p_m Pointer to receive the created SDP media. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_endpt_create_audio_sdp(pjmedia_endpt *endpt, + pj_pool_t *pool, + const pjmedia_sock_info*si, + unsigned options, + pjmedia_sdp_media **p_m); + +/** + * Create SDP media line for video media. + * + * @param endpt The media endpoint. + * @param pool Pool to allocate memory from. + * @param si Socket information. + * @param options Option flags, must be zero for now. + * @param p_m Pointer to receive the created SDP media. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_endpt_create_video_sdp(pjmedia_endpt *endpt, + pj_pool_t *pool, + const pjmedia_sock_info*si, + unsigned options, + pjmedia_sdp_media **p_m); /** * Dump media endpoint capabilities. diff --git a/pjmedia/include/pjmedia/errno.h b/pjmedia/include/pjmedia/errno.h index f47ea112..4f3a6c3e 100644 --- a/pjmedia/include/pjmedia/errno.h +++ b/pjmedia/include/pjmedia/errno.h @@ -391,7 +391,11 @@ PJ_BEGIN_DECL * Remote does not support RFC 2833 */ #define PJMEDIA_RTP_EREMNORFC2833 (PJMEDIA_ERRNO_START+107) /* 220107 */ - +/** + * @hideinitializer + * Invalid or bad format + */ +#define PJMEDIA_EBADFMT (PJMEDIA_ERRNO_START+108) /* 220108 */ /************************************************************ @@ -517,6 +521,11 @@ PJ_BEGIN_DECL * Sound frame is too large for file buffer. */ #define PJMEDIA_EFRMFILETOOBIG (PJMEDIA_ERRNO_START+183) /* 220183 */ +/** + * @hideinitializer + * Unsupported AVI file. + */ +#define PJMEDIA_EAVIUNSUPP (PJMEDIA_ERRNO_START+191) /* 220191 */ /************************************************************ diff --git a/pjmedia/include/pjmedia/event.h b/pjmedia/include/pjmedia/event.h new file mode 100644 index 00000000..ddcffc02 --- /dev/null +++ b/pjmedia/include/pjmedia/event.h @@ -0,0 +1,402 @@ +/* $Id$ */ +/* + * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com) + * + * 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_EVENT_H__ +#define __PJMEDIA_EVENT_H__ + +/** + * @file pjmedia/event.h + * @brief Event framework + */ +#include +#include +#include + +PJ_BEGIN_DECL + +/** + * @defgroup PJMEDIA_EVENT Event Framework + * @brief PJMEDIA event framework + * @{ + */ + +/** + * This enumeration describes list of media events. + */ +typedef enum pjmedia_event_type +{ + /** + * No event. + */ + PJMEDIA_EVENT_NONE, + + /** + * Media format has changed event. + */ + PJMEDIA_EVENT_FMT_CHANGED = PJMEDIA_FOURCC('F', 'M', 'C', 'H'), + + /** + * Video window is being closed. + */ + PJMEDIA_EVENT_WND_CLOSING = PJMEDIA_FOURCC('W', 'N', 'C', 'L'), + + /** + * Video window has been closed event. + */ + PJMEDIA_EVENT_WND_CLOSED = PJMEDIA_FOURCC('W', 'N', 'C', 'O'), + + /** + * Video window has been resized event. + */ + PJMEDIA_EVENT_WND_RESIZED = PJMEDIA_FOURCC('W', 'N', 'R', 'Z'), + + /** + * Mouse button has been pressed event. + */ + PJMEDIA_EVENT_MOUSE_BTN_DOWN = PJMEDIA_FOURCC('M', 'S', 'D', 'N'), + + /** + * Video key frame has just been decoded event. + */ + PJMEDIA_EVENT_KEY_FRAME_FOUND = PJMEDIA_FOURCC('I', 'F', 'R', 'F'), + + /** + * Video decoding error due to missing key frame event. + */ + PJMEDIA_EVENT_KEY_FRAME_MISSING = PJMEDIA_FOURCC('I', 'F', 'R', 'M') + +} pjmedia_event_type; + +/** + * Forward declaration for event subscription. + */ +typedef struct pjmedia_event_subscription pjmedia_event_subscription; + +/** + * Forward declaration for event publisher. + */ +typedef struct pjmedia_event_publisher pjmedia_event_publisher; + +/** + * Additional data/parameters for media format changed event + * (PJMEDIA_EVENT_FMT_CHANGED). + */ +typedef struct pjmedia_event_fmt_changed_data +{ + /** The media flow direction */ + pjmedia_dir dir; + + /** The new media format. */ + pjmedia_format new_fmt; +} pjmedia_event_fmt_changed_data; + +/** + * Additional data/parameters are not needed. + */ +typedef struct pjmedia_event_dummy_data +{ + /** Dummy data */ + int dummy; +} pjmedia_event_dummy_data; + +/** + * Additional data/parameters for window resized event + * (PJMEDIA_EVENT_WND_RESIZED). + */ +typedef struct pjmedia_event_wnd_resized_data +{ + /** + * The new window size. + */ + pjmedia_rect_size new_size; +} pjmedia_event_wnd_resized_data; + +/** + * Additional data/parameters for window closing event. + */ +typedef struct pjmedia_event_wnd_closing_data +{ + /** Consumer may set this field to PJ_TRUE to cancel the closing */ + pj_bool_t cancel; +} pjmedia_event_wnd_closing_data; + +/** Additional parameters for window changed event. */ +typedef pjmedia_event_dummy_data pjmedia_event_wnd_closed_data; + +/** Additional parameters for mouse button down event */ +typedef pjmedia_event_dummy_data pjmedia_event_mouse_btn_down_data; + +/** Additional parameters for key frame found event */ +typedef pjmedia_event_dummy_data pjmedia_event_key_frame_found_data; + +/** Additional parameters for key frame missing event */ +typedef pjmedia_event_dummy_data pjmedia_event_key_frame_missing_data; + +/** + * Maximum size of additional parameters section in pjmedia_event structure + */ +#define PJMEDIA_EVENT_DATA_MAX_SIZE sizeof(pjmedia_event_fmt_changed_data) + +/** Type of storage to hold user data in pjmedia_event structure */ +typedef char pjmedia_event_user_data[PJMEDIA_EVENT_DATA_MAX_SIZE]; + +/** + * This structure describes a media event. It consists mainly of the event + * type and additional data/parameters for the event. Event publishers need + * to use #pjmedia_event_init() to initialize this event structure with + * basic information about the event. + */ +typedef struct pjmedia_event +{ + /** + * The event type. + */ + pjmedia_event_type type; + + /** + * The media timestamp when the event occurs. + */ + pj_timestamp timestamp; + + /** + * This keeps count on the number of subscribers that have + * processed this event. + */ + unsigned proc_cnt; + + /** + * The object signature of the event publisher. Application may use + * this to check which publisher published the event. + */ + pjmedia_obj_sig epub_sig; + + /** + * Pointer information about the source of this event. This field + * is provided mainly so that the event subscribers can compare it + * against the publisher that it subscribed the events from initially, + * a publisher can republish events from other publisher. Event + * subscription must be careful when using this pointer other than for + * comparison purpose, since access to the publisher may require special + * care (e.g. mutex locking). + */ + const pjmedia_event_publisher *epub; + + /** + * Additional data/parameters about the event. The type of data + * will be specific to the event type being reported. + */ + union { + /** Media format changed event data. */ + pjmedia_event_fmt_changed_data fmt_changed; + + /** Window resized event data */ + pjmedia_event_wnd_resized_data wnd_resized; + + /** Window closing event data. */ + pjmedia_event_wnd_closing_data wnd_closing; + + /** Window closed event data */ + pjmedia_event_wnd_closed_data wnd_closed; + + /** Mouse button down event data */ + pjmedia_event_mouse_btn_down_data mouse_btn_down; + + /** Key frame found event data */ + pjmedia_event_key_frame_found_data key_frm_found; + + /** Key frame missing event data */ + pjmedia_event_key_frame_missing_data key_frm_missing; + + /** Storage for user event data */ + pjmedia_event_user_data user; + + /** Pointer to storage to user event data, if it's outside + * this struct + */ + void *ptr; + } data; +} pjmedia_event; + +/** + * The callback to receive media events. The callback should increase + * \a proc_cnt field of the event if it processes the event. + * + * @param esub The subscription that was made initially to receive + * this event. + * @param event The media event itself. + * + * @return If the callback returns non-PJ_SUCCESS, this return + * code may be propagated back to the producer. + */ +typedef pj_status_t pjmedia_event_cb(pjmedia_event_subscription *esub, + pjmedia_event *event); + +/** + * This structure keeps the data needed to maintain an event subscription. + * This data is normally kept by event publishers. + */ +struct pjmedia_event_subscription +{ + /** Standard list members */ + PJ_DECL_LIST_MEMBER(pjmedia_event_subscription); + + /** Callback that will be called by publisher to report events. */ + pjmedia_event_cb *cb; + + /** User data for this subscription */ + void *user_data; + + /** Current publisher it is subscribed to */ + pjmedia_event_publisher *subscribe_to; +}; + +/** + * This describes an event publisher. An event publisher is an object that + * maintains event subscriptions. When an event is published on behalf of + * a publisher with #pjmedia_event_publish(), that event will be propagated + * to all of the subscribers registered to the publisher. + */ +struct pjmedia_event_publisher +{ + /** The object signature of the publisher */ + pjmedia_obj_sig sig; + + /** List of subscriptions for this event publisher */ + pjmedia_event_subscription subscription_list; +}; + +/** + * Initialize event structure with basic data about the event. + * + * @param event The event to be initialized. + * @param type The event type to be set for this event. + * @param ts Event timestamp. May be set to NULL to set the event + * timestamp to zero. + * @param epub Event publisher. + */ +PJ_DECL(void) pjmedia_event_init(pjmedia_event *event, + pjmedia_event_type type, + const pj_timestamp *ts, + const pjmedia_event_publisher *epub); + +/** + * Initialize an event publisher structure. + * + * @param epub The event publisher. + * @param sig The object signature of the publisher. + */ +PJ_DECL(void) pjmedia_event_publisher_init(pjmedia_event_publisher *epub, + pjmedia_obj_sig sig); + +/** + * Initialize subscription data. + * + * @param esub The event subscription. + * @param cb The callback to receive events. + * @param user_data Arbitrary user data to be associated with the + * subscription. + */ +PJ_DECL(void) pjmedia_event_subscription_init(pjmedia_event_subscription *esub, + pjmedia_event_cb *cb, + void *user_data); + +/** + * Subscribe to events published by the specified publisher using the + * specified subscription object. The callback and user data fields of + * the subscription object must have been initialized prior to calling + * this function, and the subscription object must be kept alive throughout + * the duration of the subscription (e.g. it must not be allocated from + * the stack). + * + * Note that the subscriber may receive not only events emitted by + * the specific publisher specified in the argument, but also from other + * publishers contained by the publisher, if the publisher is republishing + * events from other publishers. + * + * @param epub The event publisher. + * @param esub The event subscription object. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_event_subscribe(pjmedia_event_publisher *epub, + pjmedia_event_subscription *esub); + +/** + * Unsubscribe the specified subscription object from publisher it is + * currently subscribed to. If the subscription object is not currently + * subscribed to anything, the function will do nothing. + * + * @param esub The event subscription object, which must be the same + * object that was given to #pjmedia_event_subscribe(). + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) +pjmedia_event_unsubscribe(pjmedia_event_subscription *esub); + +/** + * Check if the specified publisher has subscribers. + * + * @param epub The event publisher. + * + * @return PJ_TRUE if the publisher has at least one subscriber. + */ +PJ_DECL(pj_bool_t) +pjmedia_event_publisher_has_sub(pjmedia_event_publisher *epub); + +/** + * Publish the specified event to all subscribers of the specified event + * publisher. + * + * @param epub The event publisher. + * @param event The event to be published. + * + * @return PJ_SUCCESS only if all subscription callbacks returned + * PJ_SUCCESS. + */ +PJ_DECL(pj_status_t) pjmedia_event_publish(pjmedia_event_publisher *epub, + pjmedia_event *event); + +/** + * Subscribe to events produced by the source publisher in \a esrc and + * republish the events to all subscribers in \a epub publisher. + * + * @param esrc The event source from which events will be + * republished. + * @param epub Events from the event source above will be + * republished to subscribers of this publisher. + * @param esub The subscription object to be used to subscribe + * to \a esrc. This doesn't need to be initialized, + * but it must be kept alive throughout the lifetime + * of the subsciption. + * + * @return PJ_SUCCESS only if all subscription callbacks returned + * PJ_SUCCESS. + */ +PJ_DECL(pj_status_t) pjmedia_event_republish(pjmedia_event_publisher *esrc, + pjmedia_event_publisher *epub, + pjmedia_event_subscription *esub); + +/** + * @} PJMEDIA_EVENT + */ + + +PJ_END_DECL + +#endif /* __PJMEDIA_EVENT_H__ */ diff --git a/pjmedia/include/pjmedia/format.h b/pjmedia/include/pjmedia/format.h new file mode 100644 index 00000000..ac9fdb93 --- /dev/null +++ b/pjmedia/include/pjmedia/format.h @@ -0,0 +1,748 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * 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_FORMAT_H__ +#define __PJMEDIA_FORMAT_H__ + +/** + * @file pjmedia/format.h Media format + * @brief Media format + */ +#include + +/** + * @defgroup PJMEDIA_FORMAT Media format + * @ingroup PJMEDIA_TYPES + * @brief Media format + * @{ + */ + +PJ_BEGIN_DECL + +/** + * Macro for packing format from a four character code, similar to FOURCC. + * This macro is used for building the constants in pjmedia_format_id + * enumeration. + */ +#define PJMEDIA_FORMAT_PACK(C1, C2, C3, C4) PJMEDIA_FOURCC(C1, C2, C3, C4) + +/** + * This enumeration uniquely identify audio sample and/or video pixel formats. + * Some well known formats are listed here. The format ids are built by + * combining four character codes, similar to FOURCC. The format id is + * extensible, as application may define and use format ids not declared + * on this enumeration. + * + * This format id along with other information will fully describe the media + * in #pjmedia_format structure. + */ +typedef enum pjmedia_format_id +{ + /* + * Audio formats + */ + + /** 16bit signed integer linear PCM audio */ + PJMEDIA_FORMAT_L16 = 0, + + /** Alias for PJMEDIA_FORMAT_L16 */ + PJMEDIA_FORMAT_PCM = PJMEDIA_FORMAT_L16, + + /** G.711 ALAW */ + PJMEDIA_FORMAT_PCMA = PJMEDIA_FORMAT_PACK('A', 'L', 'A', 'W'), + + /** Alias for PJMEDIA_FORMAT_PCMA */ + PJMEDIA_FORMAT_ALAW = PJMEDIA_FORMAT_PCMA, + + /** G.711 ULAW */ + PJMEDIA_FORMAT_PCMU = PJMEDIA_FORMAT_PACK('u', 'L', 'A', 'W'), + + /** Aliaw for PJMEDIA_FORMAT_PCMU */ + PJMEDIA_FORMAT_ULAW = PJMEDIA_FORMAT_PCMU, + + /** AMR narrowband */ + PJMEDIA_FORMAT_AMR = PJMEDIA_FORMAT_PACK(' ', 'A', 'M', 'R'), + + /** ITU G.729 */ + PJMEDIA_FORMAT_G729 = PJMEDIA_FORMAT_PACK('G', '7', '2', '9'), + + /** Internet Low Bit-Rate Codec (ILBC) */ + PJMEDIA_FORMAT_ILBC = PJMEDIA_FORMAT_PACK('I', 'L', 'B', 'C'), + + + /* + * Video formats. + */ + /** + * 24bit RGB + */ + PJMEDIA_FORMAT_RGB24 = PJMEDIA_FORMAT_PACK('R', 'G', 'B', '3'), + + /** + * 32bit RGB with alpha channel + */ + PJMEDIA_FORMAT_RGBA = PJMEDIA_FORMAT_PACK('R', 'G', 'B', 'A'), + PJMEDIA_FORMAT_BGRA = PJMEDIA_FORMAT_PACK('B', 'G', 'R', 'A'), + + /** + * Alias for PJMEDIA_FORMAT_RGBA + */ + PJMEDIA_FORMAT_RGB32 = PJMEDIA_FORMAT_RGBA, + + /** + * Device Independent Bitmap, alias for 24 bit RGB + */ + PJMEDIA_FORMAT_DIB = PJMEDIA_FORMAT_PACK('D', 'I', 'B', ' '), + + /** + * This is a packed 4:4:4/32bpp format, where each pixel is encoded as + * four consecutive bytes, arranged in the following sequence: V0, U0, + * Y0, A0. Source: + * http://msdn.microsoft.com/en-us/library/dd206750%28v=VS.85%29.aspx#ayuv + */ + PJMEDIA_FORMAT_AYUV = PJMEDIA_FORMAT_PACK('A', 'Y', 'U', 'V'), + + /** + * This is packed 4:2:2/16bpp YUV format, the data can be treated as + * an array of unsigned char values, where the first byte contains + * the first Y sample, the second byte contains the first U (Cb) sample, + * the third byte contains the second Y sample, and the fourth byte + * contains the first V (Cr) sample, and so forth. Source: + * http://msdn.microsoft.com/en-us/library/dd206750%28v=VS.85%29.aspx#yuy2 + */ + PJMEDIA_FORMAT_YUY2 = PJMEDIA_FORMAT_PACK('Y', 'U', 'Y', '2'), + + /** + * This format is the same as the YUY2 format except the byte order is + * reversed -- that is, the chroma and luma bytes are flipped. If the + * image is addressed as an array of two little-endian WORD values, the + * first WORD contains U in the LSBs and Y0 in the MSBs, and the second + * WORD contains V in the LSBs and Y1 in the MSBs. Source: + * http://msdn.microsoft.com/en-us/library/dd206750%28v=VS.85%29.aspx#uyvy + */ + PJMEDIA_FORMAT_UYVY = PJMEDIA_FORMAT_PACK('U', 'Y', 'V', 'Y'), + + /** + * This format is the same as the YUY2 and UYVY format except the byte + * order is reversed -- that is, the chroma and luma bytes are flipped. + * If the image is addressed as an array of two little-endian WORD values, + * the first WORD contains Y0 in the LSBs and V in the MSBs, and the second + * WORD contains Y1 in the LSBs and U in the MSBs. + */ + PJMEDIA_FORMAT_YVYU = PJMEDIA_FORMAT_PACK('Y', 'V', 'Y', 'U'), + + /** + * This is planar 4:2:0/12bpp YUV format, the data can be treated as + * three planes of color components, where the first plane contains + * only the Y samples, the second plane contains only the U (Cb) samples, + * and the third plane contains only the V (Cr) sample. + */ + PJMEDIA_FORMAT_I420 = PJMEDIA_FORMAT_PACK('I', '4', '2', '0'), + + /** + * IYUV is alias for I420. + */ + PJMEDIA_FORMAT_IYUV = PJMEDIA_FORMAT_I420, + + /** + * This is planar 4:2:2/16bpp YUV format. + */ + PJMEDIA_FORMAT_YV12 = PJMEDIA_FORMAT_PACK('Y', 'V', '1', '2'), + + /** + * The JPEG version of planar 4:2:0/12bpp YUV format. + */ + PJMEDIA_FORMAT_I420JPEG = PJMEDIA_FORMAT_PACK('J', '4', '2', '0'), + + /** + * The JPEG version of planar 4:2:2/16bpp YUV format. + */ + PJMEDIA_FORMAT_I422JPEG = PJMEDIA_FORMAT_PACK('J', '4', '2', '2'), + + /** + * Encoded video formats + */ + + PJMEDIA_FORMAT_H261 = PJMEDIA_FORMAT_PACK('H', '2', '6', '1'), + PJMEDIA_FORMAT_H263 = PJMEDIA_FORMAT_PACK('H', '2', '6', '3'), + PJMEDIA_FORMAT_H263P = PJMEDIA_FORMAT_PACK('P', '2', '6', '3'), + PJMEDIA_FORMAT_H264 = PJMEDIA_FORMAT_PACK('H', '2', '6', '4'), + + PJMEDIA_FORMAT_MJPEG = PJMEDIA_FORMAT_PACK('M', 'J', 'P', 'G'), + PJMEDIA_FORMAT_MPEG1VIDEO = PJMEDIA_FORMAT_PACK('M', 'P', '1', 'V'), + PJMEDIA_FORMAT_MPEG2VIDEO = PJMEDIA_FORMAT_PACK('M', 'P', '2', 'V'), + PJMEDIA_FORMAT_MPEG4 = PJMEDIA_FORMAT_PACK('M', 'P', 'G', '4'), + PJMEDIA_FORMAT_XVID = PJMEDIA_FORMAT_PACK('x', 'v', 'i', 'd'), + +} pjmedia_format_id; + +/** + * This enumeration specifies what type of detail is included in a + * #pjmedia_format structure. + */ +typedef enum pjmedia_format_detail_type +{ + /** Format detail is not specified. */ + PJMEDIA_FORMAT_DETAIL_NONE, + + /** Audio format detail. */ + PJMEDIA_FORMAT_DETAIL_AUDIO, + + /** Video format detail. */ + PJMEDIA_FORMAT_DETAIL_VIDEO, + + /** Number of format detail type that has been defined. */ + PJMEDIA_FORMAT_DETAIL_MAX + +} pjmedia_format_detail_type; + +/** + * This structure is put in \a detail field of #pjmedia_format to describe + * detail information about an audio media. + */ +typedef struct pjmedia_audio_format_detail +{ + unsigned clock_rate; /**< Audio clock rate in samples or Hz. */ + unsigned channel_count; /**< Number of channels. */ + unsigned frame_time_usec;/**< Frame interval, in microseconds. */ + unsigned bits_per_sample;/**< Number of bits per sample. */ + pj_uint32_t avg_bps; /**< Average bitrate */ + pj_uint32_t max_bps; /**< Maximum bitrate */ +} pjmedia_audio_format_detail; + +/** + * This structure is put in \a detail field of #pjmedia_format to describe + * detail information about a video media. + * + * Additional information about a video format can also be retrieved by + * calling #pjmedia_get_video_format_info(). + */ +typedef struct pjmedia_video_format_detail +{ + pjmedia_rect_size size; /**< Video size (width, height) */ + pjmedia_ratio fps; /**< Number of frames per second. */ + pj_uint32_t avg_bps;/**< Average bitrate. */ + pj_uint32_t max_bps;/**< Maximum bitrate. */ +} pjmedia_video_format_detail; + +/** + * This macro declares the size of the detail section in #pjmedia_format + * to be reserved for user defined detail. + */ +#ifndef PJMEDIA_FORMAT_DETAIL_USER_SIZE +# define PJMEDIA_FORMAT_DETAIL_USER_SIZE 1 +#endif + +/** + * This structure contains all the information needed to completely describe + * a media. + */ +typedef struct pjmedia_format +{ + /** + * The format id that specifies the audio sample or video pixel format. + * Some well known formats ids are declared in pjmedia_format_id + * enumeration. + * + * @see pjmedia_format_id + */ + pj_uint32_t id; + + /** + * The top-most type of the media, as an information. + */ + pjmedia_type type; + + /** + * The type of detail structure in the \a detail pointer. + */ + pjmedia_format_detail_type detail_type; + + /** + * Detail section to describe the media. + */ + union + { + /** + * Detail section for audio format. + */ + pjmedia_audio_format_detail aud; + + /** + * Detail section for video format. + */ + pjmedia_video_format_detail vid; + + /** + * Reserved area for user-defined format detail. + */ + char user[PJMEDIA_FORMAT_DETAIL_USER_SIZE]; + } det; + +} pjmedia_format; + +/** + * This enumeration describes video color model. It mostly serves as + * information only. + */ +typedef enum pjmedia_color_model +{ + /** The color model is unknown or unspecified. */ + PJMEDIA_COLOR_MODEL_NONE, + + /** RGB color model. */ + PJMEDIA_COLOR_MODEL_RGB, + + /** YUV color model. */ + PJMEDIA_COLOR_MODEL_YUV +} pjmedia_color_model; + +/** + * This structure holds information to apply a specific video format + * against size and buffer information, and get additional information + * from it. To do that, application fills up the input fields of this + * structure, and give this structure to \a apply_fmt() function + * of #pjmedia_video_format_info structure. + */ +typedef struct pjmedia_video_apply_fmt_param +{ + /* input fields: */ + + /** + * [IN] The image size. This field is mandatory, and has to be set + * correctly prior to calling \a apply_fmt() function. + */ + pjmedia_rect_size size; + + /** + * [IN] Pointer to the buffer that holds the frame. The \a apply_fmt() + * function uses this pointer to calculate the pointer for each video + * planes of the media. This field is optional -- however, the + * \a apply_fmt() would still fill up the \a planes[] array with the + * correct pointer even though the buffer is set to NULL. This could be + * useful to calculate the size (in bytes) of each plane. + */ + pj_uint8_t *buffer; + + /* output fields: */ + + /** + * [OUT] The size (in bytes) required of the buffer to hold the video + * frame of the particular frame size (width, height). + */ + pj_size_t framebytes; + + /** + * [OUT] Array of strides value (in bytes) for each video plane. + */ + int strides[PJMEDIA_MAX_VIDEO_PLANES]; + + /** + * [OUT] Array of pointers to each of the video planes. The values are + * calculated from the \a buffer field. + */ + pj_uint8_t *planes[PJMEDIA_MAX_VIDEO_PLANES]; + + /** + * [OUT] Array of video plane sizes. + */ + pj_size_t plane_bytes[PJMEDIA_MAX_VIDEO_PLANES]; + +} pjmedia_video_apply_fmt_param; + +/** + * This structure holds information to describe a video format. Application + * can retrieve this structure by calling #pjmedia_get_video_format_info() + * funcion. + */ +typedef struct pjmedia_video_format_info +{ + /** + * The unique format ID of the media. Well known format ids are declared + * in pjmedia_format_id enumeration. + */ + pj_uint32_t id; + + /** + * Null terminated string containing short identification about the + * format. + */ + char name[8]; + + /** + * Information about the color model of this video format. + */ + pjmedia_color_model color_model; + + /** + * Number of bits needed to store one pixel of this video format. + */ + pj_uint8_t bpp; + + /** + * Number of video planes that this format uses. Value 1 indicates + * packed format, while value greater than 1 indicates planar format. + */ + pj_uint8_t plane_cnt; + + /** + * Pointer to function to apply this format against size and buffer + * information in pjmedia_video_apply_fmt_param argument. Application + * uses this function to obtain various information such as the + * memory size of a frame buffer, strides value of the image, the + * location of the planes, and so on. See pjmedia_video_apply_fmt_param + * for additional information. + * + * @param vfi The video format info. + * @param vafp The parameters to investigate. + * + * @return PJ_SUCCESS if the function has calculated the + * information in \a vafp successfully. + */ + pj_status_t (*apply_fmt)(const struct pjmedia_video_format_info *vfi, + pjmedia_video_apply_fmt_param *vafp); + +} pjmedia_video_format_info; + + +/***************************************************************************** + * UTILITIES: + */ + +/** + * General utility routine to calculate samples per frame value from clock + * rate, ptime (in usec), and channel count. Application should use this + * macro whenever possible due to possible overflow in the math calculation. + * + * @param clock_rate Clock rate. + * @param usec_ptime Frame interval, in microsecond. + * @param channel_count Number of channels. + * + * @return The samples per frame value. + */ +PJ_INLINE(unsigned) PJMEDIA_SPF(unsigned clock_rate, unsigned usec_ptime, + unsigned channel_count) +{ +#if PJ_HAS_INT64 + return ((unsigned)((pj_uint64_t)usec_ptime * \ + clock_rate / channel_count / 1000000)); +#elif PJ_HAS_FLOATING_POINT + return ((unsigned)(1.0*usec_ptime * clock_rate / channel_count / 1000000)); +#else + return ((unsigned)(usec_ptime / 1000L * clock_rate / \ + channel_count / 1000)); +#endif +} + +/** + * Variant of #PJMEDIA_SPF() which takes frame rate instead of ptime. + */ +PJ_INLINE(unsigned) PJMEDIA_SPF2(unsigned clock_rate, const pjmedia_ratio *fr, + unsigned channel_count) +{ +#if PJ_HAS_INT64 + return ((unsigned)((pj_uint64_t)clock_rate * fr->denum \ + / fr->num / channel_count)); +#elif PJ_HAS_FLOATING_POINT + return ((unsigned)(1.0* clock_rate * fr->denum / fr->num /channel_count)); +#else + return ((unsigned)(1L * clock_rate * fr->denum / fr->num / channel_count)); +#endif +} + + +/** + * Utility routine to calculate frame size (in bytes) from bitrate and frame + * interval values. Application should use this macro whenever possible due + * to possible overflow in the math calculation. + * + * @param bps The bitrate of the stream. + * @param usec_ptime Frame interval, in microsecond. + * + * @return Frame size in bytes. + */ +PJ_INLINE(unsigned) PJMEDIA_FSZ(unsigned bps, unsigned usec_ptime) +{ +#if PJ_HAS_INT64 + return ((unsigned)((pj_uint64_t)bps * usec_ptime / PJ_UINT64(8000000))); +#elif PJ_HAS_FLOATING_POINT + return ((unsigned)(1.0 * bps * usec_ptime / 8000000.0)); +#else + return ((unsigned)(bps / 8L * usec_ptime / 1000000)); +#endif +} + +/** + * General utility routine to calculate ptime value from frame rate. + * Application should use this macro whenever possible due to possible + * overflow in the math calculation. + * + * @param frame_rate Frame rate + * + * @return The ptime value (in usec). + */ +PJ_INLINE(unsigned) PJMEDIA_PTIME(const pjmedia_ratio *frame_rate) +{ +#if PJ_HAS_INT64 + return ((unsigned)((pj_uint64_t)1000000 * \ + frame_rate->denum / frame_rate->num)); +#elif PJ_HAS_FLOATING_POINT + return ((unsigned)(1000000.0 * frame_rate->denum / \ + frame_rate->num)); +#else + return ((unsigned)((1000L * frame_rate->denum / \ + frame_rate->num) * 1000); +#endif +} + +/** + * Utility to retrieve samples_per_frame value from + * pjmedia_audio_format_detail. + * + * @param pafd Pointer to pjmedia_audio_format_detail + * @return Samples per frame + */ +PJ_INLINE(unsigned) PJMEDIA_AFD_SPF(const pjmedia_audio_format_detail *pafd) +{ + return PJMEDIA_SPF(pafd->clock_rate, pafd->frame_time_usec, + pafd->channel_count); +} + +/** + * Utility to retrieve average frame size from pjmedia_audio_format_detail. + * The average frame size is derived from the average bitrate of the audio + * stream. + * + * @param afd Pointer to pjmedia_audio_format_detail + * @return Average frame size. + */ +PJ_INLINE(unsigned) PJMEDIA_AFD_AVG_FSZ(const pjmedia_audio_format_detail *afd) +{ + return PJMEDIA_FSZ(afd->avg_bps, afd->frame_time_usec); +} + +/** + * Utility to retrieve maximum frame size from pjmedia_audio_format_detail. + * The maximum frame size is derived from the maximum bitrate of the audio + * stream. + * + * @param afd Pointer to pjmedia_audio_format_detail + * @return Average frame size. + */ +PJ_INLINE(unsigned) PJMEDIA_AFD_MAX_FSZ(const pjmedia_audio_format_detail *afd) +{ + return PJMEDIA_FSZ(afd->max_bps, afd->frame_time_usec); +} + + +/** + * Initialize the format as audio format with the specified parameters. + * + * @param fmt The format to be initialized. + * @param fmt_id Format ID. See #pjmedia_format_id + * @param clock_rate Audio clock rate. + * @param channel_count Number of channels. + * @param bits_per_sample Number of bits per sample. + * @param frame_time_usec Frame interval, in microsecond. + * @param avg_bps Average bitrate. + * @param max_bps Maximum bitrate. + */ +PJ_DECL(void) pjmedia_format_init_audio(pjmedia_format *fmt, + pj_uint32_t fmt_id, + unsigned clock_rate, + unsigned channel_count, + unsigned bits_per_sample, + unsigned frame_time_usec, + pj_uint32_t avg_bps, + pj_uint32_t max_bps); + +/** + * Initialize the format as video format with the specified parameters. + * A format manager should have been created, as this function will need + * to consult to a format manager in order to fill in detailed + * information about the format. + * + * @param fmt The format to be initialised. + * @param fmt_id Format ID. See #pjmedia_format_id + * @param width Image width. + * @param height Image heigth. + * @param fps_num FPS numerator. + * @param fps_denum FPS denumerator. + * @param avg_bps Average bitrate. + * @param max_bps Maximum bitrate. + */ +PJ_DECL(void) pjmedia_format_init_video(pjmedia_format *fmt, + pj_uint32_t fmt_id, + unsigned width, + unsigned height, + unsigned fps_num, + unsigned fps_denum); + +/** + * Copy format to another. + * + * @param dst The destination format. + * @param src The source format. + * + * @return Pointer to destination format. + */ +PJ_DECL(pjmedia_format*) pjmedia_format_copy(pjmedia_format *dst, + const pjmedia_format *src); + +/** + * Check if the format contains audio format, and retrieve the audio format + * detail in the format. + * + * @param fmt The format structure. + * @param assert_valid If this is set to non-zero, an assertion will be + * raised if the detail type is not audio or if the + * the detail is NULL. + * + * @return The instance of audio format detail in the format + * structure, or NULL if the format doesn't contain + * audio detail. + */ +PJ_DECL(pjmedia_audio_format_detail*) +pjmedia_format_get_audio_format_detail(const pjmedia_format *fmt, + pj_bool_t assert_valid); + +/** + * Check if the format contains video format, and retrieve the video format + * detail in the format. + * + * @param fmt The format structure. + * @param assert_valid If this is set to non-zero, an assertion will be + * raised if the detail type is not video or if the + * the detail is NULL. + * + * @return The instance of video format detail in the format + * structure, or NULL if the format doesn't contain + * video detail. + */ +PJ_DECL(pjmedia_video_format_detail*) +pjmedia_format_get_video_format_detail(const pjmedia_format *fmt, + pj_bool_t assert_valid); + +/***************************************************************************** + * FORMAT MANAGEMENT: + */ + +/** + * Opaque data type for video format manager. The video format manager manages + * the repository of video formats that the framework recognises. Typically it + * is a singleton instance, although application may instantiate more than one + * instances of this if required. + */ +typedef struct pjmedia_video_format_mgr pjmedia_video_format_mgr; + + +/** + * Create a new video format manager instance. This will also set the pointer + * to the singleton instance if the value is still NULL. + * + * @param pool The pool to allocate memory. + * @param max_fmt Maximum number of formats to accommodate. + * @param options Option flags. Must be zero for now. + * @param p_mgr Pointer to hold the created instance. + * + * @return PJ_SUCCESS on success, or the appripriate error value. + */ +PJ_DECL(pj_status_t) +pjmedia_video_format_mgr_create(pj_pool_t *pool, + unsigned max_fmt, + unsigned options, + pjmedia_video_format_mgr **p_mgr); + +/** + * Get the singleton instance of the video format manager. + * + * @return The instance. + */ +PJ_DECL(pjmedia_video_format_mgr*) pjmedia_video_format_mgr_instance(void); + +/** + * Manually assign a specific video manager instance as the singleton + * instance. Normally this is not needed if only one instance is ever + * going to be created, as the library automatically assign the singleton + * instance. + * + * @param mgr The instance to be used as the singleton instance. + * Application may specify NULL to clear the singleton + * singleton instance. + */ +PJ_DECL(void) +pjmedia_video_format_mgr_set_instance(pjmedia_video_format_mgr *mgr); + +/** + * Retrieve a video format info for the specified format id. + * + * @param mgr The video format manager. Specify NULL to use + * the singleton instance (however, a video format + * manager still must have been created prior to + * calling this function). + * @param id The format id which format info is to be + * retrieved. + * + * @return The video format info. + */ +PJ_DECL(const pjmedia_video_format_info*) +pjmedia_get_video_format_info(pjmedia_video_format_mgr *mgr, + pj_uint32_t id); + +/** + * Register a new video format to the framework. By default, built-in + * formats will be registered automatically to the format manager when + * it is created (note: built-in formats are ones which format id is + * listed in pjmedia_format_id enumeration). This function allows + * application to use user defined format id by registering that format + * into the framework. + * + * @param mgr The video format manager. Specify NULL to use + * the singleton instance (however, a video format + * manager still must have been created prior to + * calling this function). + * @param vfi The video format info to be registered. This + * structure must remain valid until the format + * manager is destroyed. + * + * @return PJ_SUCCESS on success, or the appripriate error value. + */ +PJ_DECL(pj_status_t) +pjmedia_register_video_format_info(pjmedia_video_format_mgr *mgr, + pjmedia_video_format_info *vfi); + +/** + * Destroy a video format manager. If the manager happens to be the singleton + * instance, the singleton instance will be set to NULL. + * + * @param mgr The video format manager. Specify NULL to use + * the singleton instance (however, a video format + * manager still must have been created prior to + * calling this function). + */ +PJ_DECL(void) pjmedia_video_format_mgr_destroy(pjmedia_video_format_mgr *mgr); + +PJ_END_DECL + +/** + * @} + */ + +#endif /* __PJMEDIA_FORMAT_H__ */ + diff --git a/pjmedia/include/pjmedia/frame.h b/pjmedia/include/pjmedia/frame.h new file mode 100644 index 00000000..faa33af0 --- /dev/null +++ b/pjmedia/include/pjmedia/frame.h @@ -0,0 +1,332 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * 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_FRAME_H__ +#define __PJMEDIA_FRAME_H__ + +/** + * @file pjmedia/frame.h Media frame + * @brief Frame + */ +#include +#include + +/** + * @defgroup PJMEDIA_FRAME Media frame + * @ingroup PJMEDIA_TYPES + * @brief Frame + * @{ + */ + +PJ_BEGIN_DECL + + +/** + * Types of media frame. + */ +typedef enum pjmedia_frame_type +{ + PJMEDIA_FRAME_TYPE_NONE, /**< No frame. */ + PJMEDIA_FRAME_TYPE_AUDIO, /**< Normal audio frame. */ + PJMEDIA_FRAME_TYPE_EXTENDED, /**< Extended audio frame. */ + PJMEDIA_FRAME_TYPE_VIDEO /**< Video frame. */ + +} pjmedia_frame_type; + + +/** + * This structure describes a media frame. + */ +typedef struct pjmedia_frame +{ + pjmedia_frame_type type; /**< Frame type. */ + void *buf; /**< Pointer to buffer. */ + pj_size_t size; /**< Frame size in bytes. */ + pj_timestamp timestamp; /**< Frame timestamp. */ + pj_uint32_t bit_info; /**< Bit info of the frame, sample case: + a frame may not exactly start and end + at the octet boundary, so this field + may be used for specifying start & + end bit offset. */ +} pjmedia_frame; + + +/** + * The pjmedia_frame_ext is used to carry a more complex audio frames than + * the typical PCM audio frames, and it is signaled by setting the "type" + * field of a pjmedia_frame to PJMEDIA_FRAME_TYPE_EXTENDED. With this set, + * application may typecast pjmedia_frame to pjmedia_frame_ext. + * + * This structure may contain more than one audio frames, which subsequently + * will be called subframes in this structure. The subframes section + * immediately follows the end of this structure, and each subframe is + * represented by pjmedia_frame_ext_subframe structure. Every next + * subframe immediately follows the previous subframe, and all subframes + * are byte-aligned although its payload may not be byte-aligned. + */ + +#pragma pack(1) +typedef struct pjmedia_frame_ext { + pjmedia_frame base; /**< Base frame info */ + pj_uint16_t samples_cnt; /**< Number of samples in this frame */ + pj_uint16_t subframe_cnt; /**< Number of (sub)frames in this frame */ + + /* Zero or more (sub)frames follows immediately after this, + * each will be represented by pjmedia_frame_ext_subframe + */ +} pjmedia_frame_ext; +#pragma pack() + +/** + * This structure represents the individual subframes in the + * pjmedia_frame_ext structure. + */ +#pragma pack(1) +typedef struct pjmedia_frame_ext_subframe { + pj_uint16_t bitlen; /**< Number of bits in the data */ + pj_uint8_t data[1]; /**< Start of encoded data */ +} pjmedia_frame_ext_subframe; + +#pragma pack() + +/** + * Copy one frame to another. If the destination frame's size is smaller than + * the source frame's, the destination buffer will be truncated. + * + * @param src Source frame. + * @param dst Destination frame. + */ +PJ_INLINE(void) pjmedia_frame_copy(pjmedia_frame *dst, + const pjmedia_frame *src) +{ + dst->type = src->type; + dst->timestamp = src->timestamp; + dst->bit_info = src->bit_info; + dst->size = (dst->size < src->size? dst->size: src->size); + pj_memcpy(dst->buf, src->buf, dst->size); +} + +/** + * Append one subframe to #pjmedia_frame_ext. + * + * @param frm The #pjmedia_frame_ext. + * @param src Subframe data. + * @param bitlen Length of subframe, in bits. + * @param samples_cnt Number of audio samples in subframe. + */ +PJ_INLINE(void) pjmedia_frame_ext_append_subframe(pjmedia_frame_ext *frm, + const void *src, + unsigned bitlen, + unsigned samples_cnt) +{ + pjmedia_frame_ext_subframe *fsub; + pj_uint8_t *p; + unsigned i; + + p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext); + for (i = 0; i < frm->subframe_cnt; ++i) { + fsub = (pjmedia_frame_ext_subframe*) p; + p += sizeof(fsub->bitlen) + ((fsub->bitlen+7) >> 3); + } + + fsub = (pjmedia_frame_ext_subframe*) p; + fsub->bitlen = (pj_uint16_t)bitlen; + if (bitlen) + pj_memcpy(fsub->data, src, (bitlen+7) >> 3); + + frm->subframe_cnt++; + frm->samples_cnt = (pj_uint16_t)(frm->samples_cnt + samples_cnt); +} + +/** + * Get a subframe from #pjmedia_frame_ext. + * + * @param frm The #pjmedia_frame_ext. + * @param n Subframe index, zero based. + * + * @return The n-th subframe, or NULL if n is out-of-range. + */ +PJ_INLINE(pjmedia_frame_ext_subframe*) +pjmedia_frame_ext_get_subframe(const pjmedia_frame_ext *frm, unsigned n) +{ + pjmedia_frame_ext_subframe *sf = NULL; + + if (n < frm->subframe_cnt) { + pj_uint8_t *p; + unsigned i; + + p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext); + for (i = 0; i < n; ++i) { + sf = (pjmedia_frame_ext_subframe*) p; + p += sizeof(sf->bitlen) + ((sf->bitlen+7) >> 3); + } + + sf = (pjmedia_frame_ext_subframe*) p; + } + + return sf; +} + +/** + * Extract all frame payload to the specified buffer. + * + * @param frm The frame. + * @param dst Destination buffer. + * @param maxlen Maximum size to copy (i.e. the size of the + * destination buffer). + * + * @return Total size of payload copied. + */ +PJ_INLINE(unsigned) +pjmedia_frame_ext_copy_payload(const pjmedia_frame_ext *frm, + void *dst, + unsigned maxlen) +{ + unsigned i, copied=0; + for (i=0; isubframe_cnt; ++i) { + pjmedia_frame_ext_subframe *sf; + unsigned sz; + + sf = pjmedia_frame_ext_get_subframe(frm, i); + if (!sf) + continue; + + sz = ((sf->bitlen + 7) >> 3); + if (sz + copied > maxlen) + break; + + pj_memcpy(((pj_uint8_t*)dst) + copied, sf->data, sz); + copied += sz; + } + return copied; +} + + +/** + * Pop out first n subframes from #pjmedia_frame_ext. + * + * @param frm The #pjmedia_frame_ext. + * @param n Number of first subframes to be popped out. + * + * @return PJ_SUCCESS when successful. + */ +PJ_INLINE(pj_status_t) +pjmedia_frame_ext_pop_subframes(pjmedia_frame_ext *frm, unsigned n) +{ + pjmedia_frame_ext_subframe *sf; + pj_uint8_t *move_src; + unsigned move_len; + + if (frm->subframe_cnt <= n) { + frm->subframe_cnt = 0; + frm->samples_cnt = 0; + return PJ_SUCCESS; + } + + move_src = (pj_uint8_t*)pjmedia_frame_ext_get_subframe(frm, n); + sf = pjmedia_frame_ext_get_subframe(frm, frm->subframe_cnt-1); + move_len = (pj_uint8_t*)sf - move_src + sizeof(sf->bitlen) + + ((sf->bitlen+7) >> 3); + pj_memmove((pj_uint8_t*)frm+sizeof(pjmedia_frame_ext), + move_src, move_len); + + frm->samples_cnt = (pj_uint16_t) + (frm->samples_cnt - n*frm->samples_cnt/frm->subframe_cnt); + frm->subframe_cnt = (pj_uint16_t) (frm->subframe_cnt - n); + + return PJ_SUCCESS; +} + + +/** + * This is a general purpose function set PCM samples to zero. + * Since this function is needed by many parts of the library, + * by putting this functionality in one place, it enables some. + * clever people to optimize this function. + * + * @param samples The 16bit PCM samples. + * @param count Number of samples. + */ +PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count) +{ +#if 1 + pj_bzero(samples, (count<<1)); +#elif 0 + unsigned i; + for (i=0; i>= 1; + for (i=0; i>= 1; + for (i=0; i>= 1; + for (i=0; i +#include +#include +#include +#include +#include #include #include @@ -183,6 +187,12 @@ PJ_BEGIN_DECL +/** + * Create 32bit port signature from ASCII characters. + */ +#define PJMEDIA_PORT_SIG(a,b,c,d) PJMEDIA_OBJ_SIG(a,b,c,d) + + /** * Port operation setting. */ @@ -220,19 +230,133 @@ typedef struct pjmedia_port_info { pj_str_t name; /**< Port name. */ pj_uint32_t signature; /**< Port signature. */ - pjmedia_type type; /**< Media type. */ - pj_bool_t has_info; /**< Has info? */ - pj_bool_t need_info; /**< Need info on connect? */ - unsigned pt; /**< Payload type (can be dynamic). */ - pjmedia_format format; /**< Format. */ - pj_str_t encoding_name; /**< Encoding name. */ - unsigned clock_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 bytes per frame. */ + pjmedia_dir dir; /**< Port direction. */ + pjmedia_format fmt; /**< Format. */ } pjmedia_port_info; +/** + * Utility to retrieve audio clock rate/sampling rate value from + * pjmedia_port_info. + * + * @param pia Pointer to port info containing audio format. + * @return Audio clock rate. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_SRATE(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return pia->fmt.det.aud.clock_rate; +} + +/** + * Utility to retrieve audio channel count value from pjmedia_port_info. + * + * @param pia Pointer to port info containing audio format. + * @return Audio channel count. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return pia->fmt.det.aud.channel_count; +} + +/** + * Utility to retrieve audio bits per sample value from pjmedia_port_info. + * + * @param pia Pointer to port info containing audio format. + * @return Number of bits per sample. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_BITS(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return pia->fmt.det.aud.bits_per_sample; +} + +/** + * Utility to retrieve audio frame interval (ptime) value from + * pjmedia_port_info. + * + * @param pia Pointer to port info containing audio format. + * @return Frame interval in msec. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_PTIME(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return pia->fmt.det.aud.frame_time_usec / 1000; +} + +/** + * This is a utility routine to retrieve the audio samples_per_frame value + * from port info. + * + * @param pia Pointer to port info containing audio format. + * @return Samples per frame value. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_SPF(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return PJMEDIA_AFD_SPF(&pia->fmt.det.aud); +} + +/** + * This is a utility routine to retrieve the average bitrate value + * from port info. + * + * @param pia Pointer to port info containing audio format. + * @return Bitrate, in bits per second. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_BPS(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return pia->fmt.det.aud.avg_bps; +} + +/** + * This is a utility routine to retrieve the maximum bitrate value + * from port info. + * + * @param pia Pointer to port info containing audio format. + * @return Bitrate, in bits per second. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_BPS(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return pia->fmt.det.aud.max_bps; +} + +/** + * This is a utility routine to retrieve the average audio frame size value + * from pjmedia_port_info. + * + * @param pia Pointer to port info containing audio format. + * @return Frame size in bytes. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_FSZ(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return PJMEDIA_AFD_AVG_FSZ(&pia->fmt.det.aud); +} + +/** + * Utility to retrieve audio frame size from maximum bitrate from + * pjmedia_port_info. + * + * @param pia Pointer to port info containing audio format. + * @return Frame size in bytes. + */ +PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_FSZ(const pjmedia_port_info *pia) +{ + pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO && + pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO); + return PJMEDIA_AFD_MAX_FSZ(&pia->fmt.det.aud); +} /** * Port interface. @@ -249,12 +373,19 @@ typedef struct pjmedia_port long ldata; /**< Long data. */ } port_data; + /** + * Get clock source. + * This should only be called by #pjmedia_port_get_clock_src(). + */ + pjmedia_clock_src* (*get_clock_src)(struct pjmedia_port *this_port, + pjmedia_dir dir); + /** * Sink interface. * This should only be called by #pjmedia_port_put_frame(). */ pj_status_t (*put_frame)(struct pjmedia_port *this_port, - const pjmedia_frame *frame); + pjmedia_frame *frame); /** * Source interface. @@ -268,6 +399,11 @@ typedef struct pjmedia_port */ pj_status_t (*on_destroy)(struct pjmedia_port *this_port); + /** + * Get event publisher for this media port, if any. + */ + pjmedia_event_publisher *(*get_event_pub)(struct pjmedia_port *this_port); + } pjmedia_port; @@ -293,6 +429,37 @@ PJ_DECL(pj_status_t) pjmedia_port_info_init( pjmedia_port_info *info, unsigned bits_per_sample, unsigned samples_per_frame); +/** + * This is an auxiliary function to initialize port info for + * ports which deal with PCM audio. + * + * @param info The port info to be initialized. + * @param name Port name. + * @param signature Port signature. + * @param dir Port's direction. + * @param fmt Port's media format. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_port_info_init2(pjmedia_port_info *info, + const pj_str_t *name, + unsigned signature, + pjmedia_dir dir, + const pjmedia_format *fmt); + + +/** + * Get a clock source from the port. + * + * @param port The media port. + * @param dir Media port's direction. + * + * @return The clock source or NULL if clock source is not present + * in the port. + */ +PJ_DECL(pjmedia_clock_src *) pjmedia_port_get_clock_src( pjmedia_port *port, + pjmedia_dir dir ); + /** * Get a frame from the port (and subsequent downstream ports). @@ -314,8 +481,18 @@ PJ_DECL(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port, * @return PJ_SUCCESS on success, or the appropriate error code. */ PJ_DECL(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port, - const pjmedia_frame *frame ); + pjmedia_frame *frame ); +/** + * Get the event publisher for the media port, if any. + * + * @param port The media port. + * + * @return The event publisher, or NULL if the port does not publish + * events. + */ +PJ_DECL(pjmedia_event_publisher*) +pjmedia_port_get_event_publisher(pjmedia_port *port); /** * Destroy port (and subsequent downstream ports) diff --git a/pjmedia/include/pjmedia/sdp.h b/pjmedia/include/pjmedia/sdp.h index 9e67ce46..cd89b847 100644 --- a/pjmedia/include/pjmedia/sdp.h +++ b/pjmedia/include/pjmedia/sdp.h @@ -25,7 +25,7 @@ * @brief SDP header file. */ #include - +#include /** * @defgroup PJMEDIA_SDP SDP Parsing and Data Structure @@ -276,18 +276,11 @@ pjmedia_sdp_rtpmap_to_attr( pj_pool_t *pool, /** * This structure describes SDP \a fmtp attribute. */ -struct pjmedia_sdp_fmtp +typedef struct pjmedia_sdp_fmtp { pj_str_t fmt; /**< Format type. */ pj_str_t fmt_param; /**< Format specific parameter. */ -}; - - -/** - * @see pjmedia_sdp_fmtp - */ -typedef struct pjmedia_sdp_fmtp pjmedia_sdp_fmtp; - +} pjmedia_sdp_fmtp; /** @@ -374,6 +367,20 @@ PJ_DECL(pjmedia_sdp_conn*) pjmedia_sdp_conn_clone(pj_pool_t *pool, const pjmedia_sdp_conn *rhs); +/** + * Compare connection info. + * + * @param conn1 The first connection info to compare. + * @param conn1 The second connection info to compare. + * @param option Comparison option, which should be zero for now. + * + * @return PJ_SUCCESS when both connection info are equal, otherwise + * returns PJMEDIA_SDP_ECONNNOTEQUAL. + */ +PJ_DECL(pj_status_t) pjmedia_sdp_conn_cmp(const pjmedia_sdp_conn *conn1, + const pjmedia_sdp_conn *conn2, + unsigned option); + /* ************************************************************************** * SDP BANDWIDTH INFO diff --git a/pjmedia/include/pjmedia/sdp_neg.h b/pjmedia/include/pjmedia/sdp_neg.h index bc36b19e..bc8c52cb 100644 --- a/pjmedia/include/pjmedia/sdp_neg.h +++ b/pjmedia/include/pjmedia/sdp_neg.h @@ -663,6 +663,95 @@ PJ_DECL(pj_status_t) pjmedia_sdp_neg_negotiate( pj_pool_t *pool, pj_bool_t allow_asym); +/** + * Enumeration of customized SDP format matching option flags. See + * #pjmedia_sdp_neg_register_fmt_match_cb() for more info. + */ +typedef enum pjmedia_sdp_neg_fmt_match_flag +{ + /** + * In generating answer, the SDP fmtp in the answer candidate may need + * to be modified by the customized SDP format matching callback to + * achieve flexible SDP negotiation, e.g: AMR fmtp 'octet-align' field + * can be adjusted with the offer when the codec implementation support + * both packetization modes octet-aligned and bandwidth-efficient. + */ + PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER = 1, + +} pjmedia_sdp_neg_fmt_match_flag; + + +/** + * The declaration of customized SDP format matching callback. See + * #pjmedia_sdp_neg_register_fmt_match_cb() for more info. + * + * @param pool The memory pool. + * @param offer The SDP media offer. + * @param o_fmt_idx Index of the format in the SDP media offer. + * @param answer The SDP media answer. + * @param a_fmt_idx Index of the format in the SDP media answer. + * @param option The format matching option, see + * #pjmedia_sdp_neg_fmt_match_flag. + * + * @return PJ_SUCCESS when the formats in offer and answer match. + */ +typedef pj_status_t (*pjmedia_sdp_neg_fmt_match_cb)(pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option); + + +/** + * Register customized SDP format matching callback function for the specified + * format. The customized SDP format matching is needed when the format + * identification in a media stream session cannot be simply determined by + * encoding name and clock rate, but also involves one or more format specific + * parameters, which are specified in SDP fmtp attribute. For example, + * an H.264 video stream is also identified by profile, level, and + * packetization-mode parameters. As those parameters are format specifics, + * the negotiation must be done by the format or codec implementation. + * + * To unregister the callback of specific format, just call this function with + * parameter #cb set to NULL. + * + * @param fmt_name The format name, e.g: "H.264", "AMR", "G7221". Note + * that the string buffer must remain valid until the + * callback is unregistered. + * @param cb The customized SDP format negotiation callback or + * NULL to unregister the specified format callback. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_sdp_neg_register_fmt_match_cb( + const pj_str_t *fmt_name, + pjmedia_sdp_neg_fmt_match_cb cb); + + +/** + * Match format in the SDP media offer and answer. The matching mechanism + * will be done by comparing the encoding name and clock rate, and if the + * custom format matching callback for the specified format is registered, + * see #pjmedia_sdp_neg_register_fmt_match_cb(), it will be called for more + * detail verification, e.g: format parameters specified in SDP fmtp. + * + * @param pool The memory pool. + * @param offer The SDP media offer. + * @param o_fmt_idx Index of the format in the SDP media offer. + * @param answer The SDP media answer. + * @param a_fmt_idx Index of the format in the SDP media answer. + * @param option The format matching option, see + * #pjmedia_sdp_neg_fmt_match_flag. + * + * @return PJ_SUCCESS when the formats in offer and answer match. + */ +PJ_DECL(pj_status_t) pjmedia_sdp_neg_fmt_match( pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option); PJ_END_DECL diff --git a/pjmedia/include/pjmedia/signatures.h b/pjmedia/include/pjmedia/signatures.h new file mode 100644 index 00000000..3d4402e9 --- /dev/null +++ b/pjmedia/include/pjmedia/signatures.h @@ -0,0 +1,217 @@ +/* $Id$ */ +/* + * Copyright (C) 2011-2011 Teluu Inc. (http://www.teluu.com) + * + * 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_SIGNATURES_H__ +#define __PJMEDIA_SIGNATURES_H__ + +/** + * @file pjmedia/signatures.h + * @brief Standard PJMEDIA object signatures + */ +#include + +PJ_BEGIN_DECL + +/** + * @defgroup PJMEDIA_SIG Object Signatures + * @ingroup PJMEDIA_BASE + * @brief Standard PJMEDIA object signatures + * @{ + * + * Object signature is a 32-bit integral value similar to FOURCC to help + * identify PJMEDIA objects such as media ports, transports, codecs, etc. + * There are several uses of this signature, for example a media port can + * use the port object signature to verify that the given port instance + * is the one that it created, and a receiver of \ref PJMEDIA_EVENT can + * use the signature of the publisher to know which object emitted the + * event. + * + * The 32-bit value of an object signature is generated by the following + * macro: + * + * \verbatim + #define PJMEDIA_SIGNATURE(a,b,c,d) (a<<24 | b<<16 | c<<8 | d) + * \endverbatim + * + * The following convention is used to maintain order to the signature + * values so that application can make use of it more effectively, and to + * avoid conflict between the values themselves. For each object type or + * class, a specific prefix will be assigned as signature, and a macro + * is created to build a signature for such object: + * + * \verbatim + Class Signature Signature creation and test macros + --------------------------------------------------------------- + Codec Cxxx PJMEDIA_SIG_CLASS_CODEC(b,c,d) + PJMEDIA_SIG_IS_CLASS_CODEC(sig) + + Audio codec CAxx PJMEDIA_SIG_CLASS_AUD_CODEC(c,d) + PJMEDIA_SIG_IS_CLASS_AUD_CODEC(sig) + + Video codec CVxx PJMEDIA_SIG_CLASS_VID_CODEC(c,d) + PJMEDIA_SIG_IS_CLASS_VID_CODEC(sig) + + Media port Pxxx PJMEDIA_SIG_CLASS_PORT(b,c,d) + PJMEDIA_SIG_IS_CLASS_PORT(sig) + + Audio media port PAxx PJMEDIA_SIG_CLASS_PORT_AUD(c,d) + PJMEDIA_SIG_IS_CLASS_PORT_AUD(sig) + + Video media port PVxx PJMEDIA_SIG_CLASS_PORT_VID(c,d) + PJMEDIA_SIG_IS_CLASS_PORT_VID(sig) + + Video device VDxx PJMEDIA_SIG_CLASS_VID_DEV(c,d) + PJMEDIA_SIG_IS_CLASS_VID_DEV(sig) + + Video other VOxx PJMEDIA_SIG_CLASS_VID_OTHER(c,d) + PJMEDIA_SIG_IS_CLASS_VID_OTHER(sig) + + Application object Axxx PJMEDIA_SIG_CLASS_APP(b,c,d) + PJMEDIA_SIG_IS_CLASS_APP(sig) + + * \endverbatim + * + * In addition, signatures created in application code should have lowercase + * letters to avoid conflict with built-in objects. + */ + +/** + * Type to store object signature. + */ +typedef pj_uint32_t pjmedia_obj_sig; + +/** + * A utility function to convert signature to four letters string. + * + * @param sig The signature value. + * @param buf Buffer to store the string, which MUST be at least + * five bytes long. + * + * @return The string. + */ +PJ_INLINE(const char*) pjmedia_sig_name(pjmedia_obj_sig sig, char buf[]) +{ + return pjmedia_fourcc_name(sig, buf); +} + +/** + * Macro to generate signature from four ASCII letters. + */ +#define PJMEDIA_SIGNATURE(a,b,c,d) PJMEDIA_FOURCC(a,b,c,d) + +/************************************************************************* + * Codec signature ('Cxxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_CODEC(b,c,d) PJMEDIA_SIGNATURE('C',b,c,d) +#define PJMEDIA_SIG_IS_CLASS_CODEC(sig) ((sig) >> 24 == 'C') + +/************************************************************************* + * Audio codec signatures ('CAxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_AUD_CODEC(c,d) PJMEDIA_SIG_CLASS_CODEC('A',c,d) +#define PJMEDIA_SIG_IS_CLASS_AUD_CODEC(s) ((s)>>24=='C' && (s)>>16=='A') + +/************************************************************************* + * Video codec signatures ('CVxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_VID_CODEC(c,d) PJMEDIA_SIG_CLASS_CODEC('V',c,d) +#define PJMEDIA_SIG_IS_CLASS_VID_CODEC(sig) ((s)>>24=='C' && (s)>>16=='V') + +#define PJMEDIA_SIG_VID_CODEC_FFMPEG PJMEDIA_SIG_CLASS_VID_CODEC('F','F') + +/************************************************************************* + * Port signatures ('Pxxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_PORT(b,c,d) PJMEDIA_SIGNATURE('P',b,c,d) +#define PJMEDIA_SIG_IS_CLASS_PORT(sig) ((sig) >> 24 == 'P') + +/************************************************************************* + * Audio ports signatures ('PAxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_PORT_AUD(c,d) PJMEDIA_SIG_CLASS_PORT('A',c,d) +#define PJMEDIA_SIG_IS_CLASS_PORT_AUD(s) ((s)>>24=='P' && (s)>>16=='A') + +#define PJMEDIA_SIG_PORT_BIDIR PJMEDIA_SIG_CLASS_PORT_AUD('B','D') +#define PJMEDIA_SIG_PORT_CONF PJMEDIA_SIG_CLASS_PORT_AUD('C','F') +#define PJMEDIA_SIG_PORT_CONF_PASV PJMEDIA_SIG_CLASS_PORT_AUD('C','P') +#define PJMEDIA_SIG_PORT_CONF_SWITCH PJMEDIA_SIG_CLASS_PORT_AUD('C','S') +#define PJMEDIA_SIG_PORT_ECHO PJMEDIA_SIG_CLASS_PORT_AUD('E','C') +#define PJMEDIA_SIG_PORT_MEM_CAPTURE PJMEDIA_SIG_CLASS_PORT_AUD('M','C') +#define PJMEDIA_SIG_PORT_MEM_PLAYER PJMEDIA_SIG_CLASS_PORT_AUD('M','P') +#define PJMEDIA_SIG_PORT_NULL PJMEDIA_SIG_CLASS_PORT_AUD('N','U') +#define PJMEDIA_SIG_PORT_RESAMPLE PJMEDIA_SIG_CLASS_PORT_AUD('R','E') +#define PJMEDIA_SIG_PORT_SPLIT_COMB PJMEDIA_SIG_CLASS_PORT_AUD('S','C') +#define PJMEDIA_SIG_PORT_SPLIT_COMB_P PJMEDIA_SIG_CLASS_PORT_AUD('S','P') +#define PJMEDIA_SIG_PORT_STEREO PJMEDIA_SIG_CLASS_PORT_AUD('S','R') +#define PJMEDIA_SIG_PORT_STREAM PJMEDIA_SIG_CLASS_PORT_AUD('S','T') +#define PJMEDIA_SIG_PORT_TONEGEN PJMEDIA_SIG_CLASS_PORT_AUD('T','O') +#define PJMEDIA_SIG_PORT_WAV_PLAYER PJMEDIA_SIG_CLASS_PORT_AUD('W','P') +#define PJMEDIA_SIG_PORT_WAV_PLAYLIST PJMEDIA_SIG_CLASS_PORT_AUD('W','Y') +#define PJMEDIA_SIG_PORT_WAV_WRITER PJMEDIA_SIG_CLASS_PORT_AUD('W','W') + + +/************************************************************************* + * Video ports signatures ('PVxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_PORT_VID(c,d) PJMEDIA_SIG_CLASS_PORT('V',c,d) +#define PJMEDIA_SIG_IS_CLASS_PORT_VID(s) ((s)>>24=='P' && (s)>>16=='V') + +/** AVI player signature. */ +#define PJMEDIA_SIG_PORT_VID_AVI_PLAYER PJMEDIA_SIG_CLASS_PORT_VID('A','V') +#define PJMEDIA_SIG_PORT_VID_STREAM PJMEDIA_SIG_CLASS_PORT_VID('S','T') +#define PJMEDIA_SIG_PORT_VID_TEE PJMEDIA_SIG_CLASS_PORT_VID('T','E') + + +/************************************************************************** + * Video device signatures ('VDxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_VID_DEV(c,d) PJMEDIA_SIGNATURE('V','D',c,d) +#define PJMEDIA_SIG_IS_CLASS_VID_DEV(s) ((s)>>24=='V' && (s)>>16=='D') + +#define PJMEDIA_SIG_VID_DEV_COLORBAR PJMEDIA_SIG_CLASS_VID_DEV('C','B') +#define PJMEDIA_SIG_VID_DEV_SDL PJMEDIA_SIG_CLASS_VID_DEV('S','D') +#define PJMEDIA_SIG_VID_DEV_V4L2 PJMEDIA_SIG_CLASS_VID_DEV('V','2') +#define PJMEDIA_SIG_VID_DEV_DSHOW PJMEDIA_SIG_CLASS_VID_DEV('D','S') +#define PJMEDIA_SIG_VID_DEV_QT PJMEDIA_SIG_CLASS_VID_DEV('Q','T') +#define PJMEDIA_SIG_VID_DEV_IOS PJMEDIA_SIG_CLASS_VID_DEV('I','P') + + +/********************************************************************* + * Other video objects ('VOxx'). Please keep the constant names sorted. + */ +#define PJMEDIA_SIG_CLASS_VID_OTHER(c,d) PJMEDIA_SIGNATURE('V','O',c,d) +#define PJMEDIA_SIG_IS_CLASS_VID_OTHER(s) ((s)>>24=='V' && (s)>>16=='O') + +#define PJMEDIA_SIG_VID_PORT PJMEDIA_SIG_CLASS_VID_OTHER('P','O') + + +/********************************************************************* + * Application class ('Axxx'). + */ +#define PJMEDIA_SIG_CLASS_APP(b,c,d) PJMEDIA_SIGNATURE('A',b,c,d) +#define PJMEDIA_SIG_IS_CLASS_APP(s) ((s)>>24=='A') + + +/** + * @} PJSIP_MSG + */ + + +PJ_END_DECL + +#endif /* __PJMEDIA_SIGNATURES_H__ */ diff --git a/pjmedia/include/pjmedia/sound_port.h b/pjmedia/include/pjmedia/sound_port.h index 4c47da43..2bc98d4d 100644 --- a/pjmedia/include/pjmedia/sound_port.h +++ b/pjmedia/include/pjmedia/sound_port.h @@ -25,6 +25,7 @@ * @brief Media port connection abstraction to sound device. */ #include +#include #include PJ_BEGIN_DECL @@ -268,6 +269,19 @@ PJ_DECL(pj_status_t) pjmedia_snd_port_get_ec_tail(pjmedia_snd_port *snd_port, unsigned *p_length); +/** + * Get a clock source from the sound port. + * + * @param snd_port The sound port. + * @param dir Sound port's direction. + * + * @return The clock source. + */ +PJ_DECL(pjmedia_clock_src *) +pjmedia_snd_port_get_clock_src( pjmedia_snd_port *snd_port, + pjmedia_dir dir ); + + /** * Connect a port to the sound device port. If the sound device port has a * sound recorder device, then this will start periodic function call to diff --git a/pjmedia/include/pjmedia/stream.h b/pjmedia/include/pjmedia/stream.h index 9e1976e9..aa8fa0bd 100644 --- a/pjmedia/include/pjmedia/stream.h +++ b/pjmedia/include/pjmedia/stream.h @@ -32,6 +32,7 @@ #include #include #include +#include #include PJ_BEGIN_DECL @@ -87,7 +88,7 @@ typedef struct pjmedia_channel pjmedia_channel; * corresponds to one "m=" line in SDP session descriptor, and it has * its own RTP/RTCP socket pair. */ -struct pjmedia_stream_info +typedef struct pjmedia_stream_info { pjmedia_type type; /**< Media type (audio, video) */ pjmedia_tp_proto proto; /**< Transport protocol (RTP/AVP, etc.) */ @@ -133,14 +134,32 @@ struct pjmedia_stream_info (see #PJMEDIA_STREAM_ENABLE_KA) is enabled? */ #endif -}; +} pjmedia_stream_info; /** - * @see pjmedia_stream_info. + * This function will initialize the stream info based on information + * in both SDP session descriptors for the specified stream index. + * The remaining information will be taken from default codec parameters. + * If socket info array is specified, the socket will be copied to the + * session info as well. + * + * @param si Stream info structure to be initialized. + * @param pool Pool to allocate memory. + * @param endpt PJMEDIA endpoint instance. + * @param local Local SDP session descriptor. + * @param remote Remote SDP session descriptor. + * @param stream_idx Media stream index in the session descriptor. + * + * @return PJ_SUCCESS if stream info is successfully initialized. */ -typedef struct pjmedia_stream_info pjmedia_stream_info; - +PJ_DECL(pj_status_t) +pjmedia_stream_info_from_sdp( pjmedia_stream_info *si, + pj_pool_t *pool, + pjmedia_endpt *endpt, + const pjmedia_sdp_session *local, + const pjmedia_sdp_session *remote, + unsigned stream_idx); /** @@ -230,6 +249,17 @@ PJ_DECL(pjmedia_transport*) pjmedia_stream_get_transport(pjmedia_stream *st); PJ_DECL(pj_status_t) pjmedia_stream_start(pjmedia_stream *stream); +/** + * Get the stream info. + * + * @param stream The media stream. + * @param info Stream info. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_stream_get_info( const pjmedia_stream *stream, + pjmedia_stream_info *info); + /** * Get the stream statistics. See also * #pjmedia_stream_get_stat_jbuf() @@ -371,6 +401,7 @@ pjmedia_stream_set_dtmf_callback(pjmedia_stream *stream, int digit), void *user_data); + /** * @} */ diff --git a/pjmedia/include/pjmedia/stream_common.h b/pjmedia/include/pjmedia/stream_common.h new file mode 100644 index 00000000..1c8b168d --- /dev/null +++ b/pjmedia/include/pjmedia/stream_common.h @@ -0,0 +1,57 @@ +/* $Id$ */ +/* + * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) + * + * 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_STREAM_COMMON_H__ +#define __PJMEDIA_STREAM_COMMON_H__ + + +/** + * @file stream_common.h + * @brief Stream common functions. + */ + +#include +#include + + +PJ_BEGIN_DECL + +/** + * This is internal function for parsing SDP format parameter of specific + * format or payload type, used by stream in generating stream info from SDP. + * + * @param pool Pool to allocate memory, if pool is NULL, the fmtp + * string pointers will point to the original string in + * the SDP media descriptor. + * @param m The SDP media containing the format parameter to + * be parsed. + * @param pt The format or payload type. + * @param fmtp The format parameter to store the parsing result. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_stream_info_parse_fmtp(pj_pool_t *pool, + const pjmedia_sdp_media *m, + unsigned pt, + pjmedia_codec_fmtp *fmtp); + + +PJ_END_DECL + + +#endif /* __PJMEDIA_STREAM_COMMON_H__ */ diff --git a/pjmedia/include/pjmedia/transport.h b/pjmedia/include/pjmedia/transport.h index 9762987b..e3e664f7 100644 --- a/pjmedia/include/pjmedia/transport.h +++ b/pjmedia/include/pjmedia/transport.h @@ -28,6 +28,7 @@ #include #include +#include /** * @defgroup PJMEDIA_TRANSPORT Media Transport @@ -256,6 +257,35 @@ typedef enum pjmedia_tranport_media_option } pjmedia_tranport_media_option; +/** + * Media socket info is used to describe the underlying sockets + * to be used as media transport. + */ +typedef struct pjmedia_sock_info +{ + /** The RTP socket handle */ + pj_sock_t rtp_sock; + + /** Address to be advertised as the local address for the RTP + * socket, which does not need to be equal as the bound + * address (for example, this address can be the address resolved + * with STUN). + */ + pj_sockaddr rtp_addr_name; + + /** The RTCP socket handle. */ + pj_sock_t rtcp_sock; + + /** Address to be advertised as the local address for the RTCP + * socket, which does not need to be equal as the bound + * address (for example, this address can be the address resolved + * with STUN). + */ + pj_sockaddr rtcp_addr_name; + +} pjmedia_sock_info; + + /** * This structure describes the operations for the stream transport. */ @@ -453,6 +483,9 @@ struct pjmedia_transport /** Transport's "virtual" function table. */ pjmedia_transport_op *op; + + /** Application/user data */ + void *user_data; }; /** diff --git a/pjmedia/include/pjmedia/transport_ice.h b/pjmedia/include/pjmedia/transport_ice.h index 74b19976..05515dc1 100644 --- a/pjmedia/include/pjmedia/transport_ice.h +++ b/pjmedia/include/pjmedia/transport_ice.h @@ -181,6 +181,30 @@ PJ_DECL(pj_status_t) pjmedia_ice_create2(pjmedia_endpt *endpt, unsigned options, pjmedia_transport **p_tp); +/** + * The same as #pjmedia_ice_create2() with additional \a user_data param. + * + * @param endpt The media endpoint. + * @param name Optional name to identify this ICE media transport + * for logging purposes. + * @param comp_cnt Number of components to be created. + * @param cfg Pointer to configuration settings. + * @param cb Optional structure containing ICE specific callbacks. + * @param options Options, see #pjmedia_transport_ice_options. + * @param user_data User data to be attached to the transport. + * @param p_tp Pointer to receive the media transport instance. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_ice_create3(pjmedia_endpt *endpt, + const char *name, + unsigned comp_cnt, + const pj_ice_strans_cfg *cfg, + const pjmedia_ice_cb *cb, + unsigned options, + void *user_data, + pjmedia_transport **p_tp); + PJ_END_DECL diff --git a/pjmedia/include/pjmedia/types.h b/pjmedia/include/pjmedia/types.h index f8ea125c..6a660f0c 100644 --- a/pjmedia/include/pjmedia/types.h +++ b/pjmedia/include/pjmedia/types.h @@ -26,8 +26,9 @@ */ #include -#include /* pjmedia_sock_info */ -#include /* pj_memcpy(), pj_memset() */ +#include +#include + /** * @defgroup PJMEDIA_PORT Media Ports Framework @@ -48,26 +49,24 @@ */ /** - * Top most media type. + * Top most media type. See also #pjmedia_type_name(). */ typedef enum pjmedia_type { - /** No type. */ - PJMEDIA_TYPE_NONE = 0, + /** Type is not specified. */ + PJMEDIA_TYPE_NONE, /** The media is audio */ - PJMEDIA_TYPE_AUDIO = 1, + PJMEDIA_TYPE_AUDIO, /** The media is video. */ - PJMEDIA_TYPE_VIDEO = 2, - - /** Unknown media type, in this case the name will be specified in - * encoding_name. - */ - PJMEDIA_TYPE_UNKNOWN = 3, + PJMEDIA_TYPE_VIDEO, /** The media is application. */ - PJMEDIA_TYPE_APPLICATION = 4 + PJMEDIA_TYPE_APPLICATION, + + /** The media type is unknown or unsupported. */ + PJMEDIA_TYPE_UNKNOWN } pjmedia_type; @@ -100,42 +99,31 @@ typedef enum pjmedia_dir /** None */ PJMEDIA_DIR_NONE = 0, - /** Encoding (outgoing to network) stream */ + /** Encoding (outgoing to network) stream, also known as capture */ PJMEDIA_DIR_ENCODING = 1, - /** Decoding (incoming from network) stream. */ - PJMEDIA_DIR_DECODING = 2, - - /** Incoming and outgoing stream. */ - PJMEDIA_DIR_ENCODING_DECODING = 3 + /** Same as encoding direction. */ + PJMEDIA_DIR_CAPTURE = PJMEDIA_DIR_ENCODING, -} pjmedia_dir; + /** Decoding (incoming from network) stream, also known as playback. */ + PJMEDIA_DIR_DECODING = 2, + /** Same as decoding. */ + PJMEDIA_DIR_PLAYBACK = PJMEDIA_DIR_DECODING, + /** Same as decoding. */ + PJMEDIA_DIR_RENDER = PJMEDIA_DIR_DECODING, -/* Alternate names for media direction: */ + /** Incoming and outgoing stream, same as PJMEDIA_DIR_CAPTURE_PLAYBACK */ + PJMEDIA_DIR_ENCODING_DECODING = 3, -/** - * Direction is capturing audio frames. - */ -#define PJMEDIA_DIR_CAPTURE PJMEDIA_DIR_ENCODING + /** Same as ENCODING_DECODING */ + PJMEDIA_DIR_CAPTURE_PLAYBACK = PJMEDIA_DIR_ENCODING_DECODING, -/** - * Direction is playback of audio frames. - */ -#define PJMEDIA_DIR_PLAYBACK PJMEDIA_DIR_DECODING + /** Same as ENCODING_DECODING */ + PJMEDIA_DIR_CAPTURE_RENDER = PJMEDIA_DIR_ENCODING_DECODING -/** - * Direction is both capture and playback. - */ -#define PJMEDIA_DIR_CAPTURE_PLAYBACK PJMEDIA_DIR_ENCODING_DECODING - - -/** - * Create 32bit port signature from ASCII characters. - */ -#define PJMEDIA_PORT_SIGNATURE(a,b,c,d) \ - (a<<24 | b<<16 | c<<8 | d) +} pjmedia_dir; /** @@ -143,384 +131,98 @@ typedef enum pjmedia_dir */ typedef struct pjmedia_endpt pjmedia_endpt; - /* * Forward declaration for stream (needed by transport). */ typedef struct pjmedia_stream pjmedia_stream; - -/** - * Media socket info is used to describe the underlying sockets - * to be used as media transport. - */ -typedef struct pjmedia_sock_info -{ - /** The RTP socket handle */ - pj_sock_t rtp_sock; - - /** Address to be advertised as the local address for the RTP - * socket, which does not need to be equal as the bound - * address (for example, this address can be the address resolved - * with STUN). - */ - pj_sockaddr rtp_addr_name; - - /** The RTCP socket handle. */ - pj_sock_t rtcp_sock; - - /** Address to be advertised as the local address for the RTCP - * socket, which does not need to be equal as the bound - * address (for example, this address can be the address resolved - * with STUN). - */ - pj_sockaddr rtcp_addr_name; - -} pjmedia_sock_info; - - /** - * Macro for packing format. + * Enumeration for picture coordinate base. */ -#define PJMEDIA_FORMAT_PACK(C1, C2, C3, C4) ( C4<<24 | C3<<16 | C2<<8 | C1 ) - -/** - * This enumeration describes format ID. - */ -typedef enum pjmedia_format_id +typedef enum pjmedia_coord_base { /** - * 16bit linear + * This specifies that the pixel [0, 0] location is at the left-top + * position. */ - PJMEDIA_FORMAT_L16 = 0, - - /** - * Alias for PJMEDIA_FORMAT_L16 - */ - PJMEDIA_FORMAT_PCM = PJMEDIA_FORMAT_L16, + PJMEDIA_COORD_BASE_LEFT_TOP, /** - * G.711 ALAW + * This specifies that the pixel [0, 0] location is at the left-bottom + * position. */ - PJMEDIA_FORMAT_PCMA = PJMEDIA_FORMAT_PACK('A', 'L', 'A', 'W'), - - /** - * Alias for PJMEDIA_FORMAT_PCMA - */ - PJMEDIA_FORMAT_ALAW = PJMEDIA_FORMAT_PCMA, - - /** - * G.711 ULAW - */ - PJMEDIA_FORMAT_PCMU = PJMEDIA_FORMAT_PACK('u', 'L', 'A', 'W'), - - /** - * Aliaw for PJMEDIA_FORMAT_PCMU - */ - PJMEDIA_FORMAT_ULAW = PJMEDIA_FORMAT_PCMU, - - /** - * AMR narrowband - */ - PJMEDIA_FORMAT_AMR = PJMEDIA_FORMAT_PACK(' ', 'A', 'M', 'R'), - - /** - * ITU G.729 - */ - PJMEDIA_FORMAT_G729 = PJMEDIA_FORMAT_PACK('G', '7', '2', '9'), - - /** - * Internet Low Bit-Rate Codec (ILBC) - */ - PJMEDIA_FORMAT_ILBC = PJMEDIA_FORMAT_PACK('I', 'L', 'B', 'C') - -} pjmedia_format_id; + PJMEDIA_COORD_BASE_LEFT_BOTTOM +} pjmedia_coord_base; /** - * Media format information. + * This structure is used to represent rational numbers. */ -typedef struct pjmedia_format +typedef struct pjmedia_ratio { - /** Format ID */ - pjmedia_format_id id; - - /** Bitrate. */ - pj_uint32_t bitrate; - - /** Flag to indicate whether VAD is enabled */ - pj_bool_t vad; - -} pjmedia_format; - - + int num; /** < Numerator. */ + int denum; /** < Denumerator. */ +} pjmedia_ratio; /** - * This is a general purpose function set PCM samples to zero. - * Since this function is needed by many parts of the library, - * by putting this functionality in one place, it enables some. - * clever people to optimize this function. - * - * @param samples The 16bit PCM samples. - * @param count Number of samples. + * This structure represent a coordinate. */ -PJ_INLINE(void) pjmedia_zero_samples(pj_int16_t *samples, unsigned count) +typedef struct pjmedia_coord { -#if 1 - pj_bzero(samples, (count<<1)); -#elif 0 - unsigned i; - for (i=0; i>= 1; - for (i=0; i>= 1; - for (i=0; i>= 1; - for (i=0; isubframe_cnt; ++i) { - fsub = (pjmedia_frame_ext_subframe*) p; - p += sizeof(fsub->bitlen) + ((fsub->bitlen+7) >> 3); - } - - fsub = (pjmedia_frame_ext_subframe*) p; - fsub->bitlen = (pj_uint16_t)bitlen; - if (bitlen) - pj_memcpy(fsub->data, src, (bitlen+7) >> 3); - - frm->subframe_cnt++; - frm->samples_cnt = (pj_uint16_t)(frm->samples_cnt + samples_cnt); -} - -/** - * Get a subframe from #pjmedia_frame_ext. - * - * @param frm The #pjmedia_frame_ext. - * @param n Subframe index, zero based. - * - * @return The n-th subframe, or NULL if n is out-of-range. - */ -PJ_INLINE(pjmedia_frame_ext_subframe*) -pjmedia_frame_ext_get_subframe(const pjmedia_frame_ext *frm, unsigned n) -{ - pjmedia_frame_ext_subframe *sf = NULL; - - if (n < frm->subframe_cnt) { - pj_uint8_t *p; - unsigned i; - - p = (pj_uint8_t*)frm + sizeof(pjmedia_frame_ext); - for (i = 0; i < n; ++i) { - sf = (pjmedia_frame_ext_subframe*) p; - p += sizeof(sf->bitlen) + ((sf->bitlen+7) >> 3); - } - - sf = (pjmedia_frame_ext_subframe*) p; - } - - return sf; -} - -/** - * Extract all frame payload to the specified buffer. + * Utility function to return the string name for a pjmedia_type. * - * @param frm The frame. - * @param dst Destination buffer. - * @param maxlen Maximum size to copy (i.e. the size of the - * destination buffer). + * @param t The media type. * - * @return Total size of payload copied. + * @return String. */ -PJ_INLINE(unsigned) -pjmedia_frame_ext_copy_payload(const pjmedia_frame_ext *frm, - void *dst, - unsigned maxlen) -{ - unsigned i, copied=0; - for (i=0; isubframe_cnt; ++i) { - pjmedia_frame_ext_subframe *sf; - unsigned sz; - - sf = pjmedia_frame_ext_get_subframe(frm, i); - if (!sf) - continue; - - sz = ((sf->bitlen + 7) >> 3); - if (sz + copied > maxlen) - break; - - pj_memcpy(((pj_uint8_t*)dst) + copied, sf->data, sz); - copied += sz; - } - return copied; -} - +PJ_DECL(const char*) pjmedia_type_name(pjmedia_type t); /** - * Pop out first n subframes from #pjmedia_frame_ext. + * A utility function to convert fourcc type of value to four letters string. * - * @param frm The #pjmedia_frame_ext. - * @param n Number of first subframes to be popped out. + * @param sig The fourcc value. + * @param buf Buffer to store the string, which MUST be at least + * five bytes long. * - * @return PJ_SUCCESS when successful. + * @return The string. */ -PJ_INLINE(pj_status_t) -pjmedia_frame_ext_pop_subframes(pjmedia_frame_ext *frm, unsigned n) +PJ_INLINE(const char*) pjmedia_fourcc_name(pj_uint32_t sig, char buf[]) { - pjmedia_frame_ext_subframe *sf; - pj_uint8_t *move_src; - unsigned move_len; - - if (frm->subframe_cnt <= n) { - frm->subframe_cnt = 0; - frm->samples_cnt = 0; - return PJ_SUCCESS; - } - - move_src = (pj_uint8_t*)pjmedia_frame_ext_get_subframe(frm, n); - sf = pjmedia_frame_ext_get_subframe(frm, frm->subframe_cnt-1); - move_len = (pj_uint8_t*)sf - move_src + sizeof(sf->bitlen) + - ((sf->bitlen+7) >> 3); - pj_memmove((pj_uint8_t*)frm+sizeof(pjmedia_frame_ext), - move_src, move_len); - - frm->samples_cnt = (pj_uint16_t) - (frm->samples_cnt - n*frm->samples_cnt/frm->subframe_cnt); - frm->subframe_cnt = (pj_uint16_t) (frm->subframe_cnt - n); - - return PJ_SUCCESS; + buf[3] = (char)((sig >> 24) & 0xFF); + buf[2] = (char)((sig >> 16) & 0xFF); + buf[1] = (char)((sig >> 8) & 0xFF); + buf[0] = (char)((sig >> 0) & 0xFF); + buf[4] = '\0'; + return buf; } diff --git a/pjmedia/include/pjmedia/vid_codec.h b/pjmedia/include/pjmedia/vid_codec.h new file mode 100644 index 00000000..40adcdcd --- /dev/null +++ b/pjmedia/include/pjmedia/vid_codec.h @@ -0,0 +1,978 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * 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_VID_CODEC_H__ +#define __PJMEDIA_VID_CODEC_H__ + + +/** + * @file vid_codec.h + * @brief Video codec framework. + */ + +#include +#include +#include +#include +#include +#include + +PJ_BEGIN_DECL + +#define PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT 8 +#define PJMEDIA_VID_CODEC_MAX_FPS_CNT 16 + +/** + * Identification used to search for codec factory that supports specific + * codec specification. + */ +typedef struct pjmedia_vid_codec_info +{ + pjmedia_format_id fmt_id; /**< Encoded format ID */ + unsigned pt; /**< Payload type */ + pj_str_t encoding_name; /**< Encoding name */ + pj_str_t encoding_desc; /**< Encoding desc */ + unsigned clock_rate; /**< Clock rate */ + pjmedia_dir dir; /**< Direction */ + unsigned dec_fmt_id_cnt; /**< # of supported encoding source + format IDs */ + pjmedia_format_id dec_fmt_id[PJMEDIA_VID_CODEC_MAX_DEC_FMT_CNT]; + /**< Supported encoding source + format IDs */ + unsigned fps_cnt; /**< # of supported frame-rates, can be + zero (support any frame-rate) */ + pjmedia_ratio fps[PJMEDIA_VID_CODEC_MAX_FPS_CNT]; + /**< Supported frame-rates */ + pj_bool_t has_rtp_pack; /**< Support RTP packetization */ +} pjmedia_vid_codec_info; + + +/** + * Detailed codec attributes used in configuring a codec and in querying + * the capability of codec factories. Default attributes of any codecs could + * be queried using #pjmedia_vid_codec_mgr_get_default_param() and modified + * using #pjmedia_vid_codec_mgr_set_default_param(). + * + * Please note that codec parameter also contains SDP specific setting, + * #dec_fmtp and #enc_fmtp, which may need to be set appropriately based on + * the effective setting. See each codec documentation for more detail. + */ +typedef struct pjmedia_vid_codec_param +{ + pjmedia_dir dir; /**< Direction */ + pjmedia_format enc_fmt; /**< Encoded format */ + pjmedia_format dec_fmt; /**< Decoded format */ + + pjmedia_codec_fmtp enc_fmtp; /**< Encoder fmtp params */ + pjmedia_codec_fmtp dec_fmtp; /**< Decoder fmtp params */ + + unsigned enc_mtu; /**< MTU or max payload size setting*/ +} pjmedia_vid_codec_param; + + +/** + * Duplicate video codec parameter. + * + * @param pool The pool. + * @param src The video codec parameter to be duplicated. + * + * @return Duplicated codec parameter. + */ +PJ_DECL(pjmedia_vid_codec_param*) pjmedia_vid_codec_param_clone( + pj_pool_t *pool, + const pjmedia_vid_codec_param *src); + +/** + * Forward declaration for video codec. + */ +typedef struct pjmedia_vid_codec pjmedia_vid_codec; + + +/** + * This structure describes codec operations. Each codec MUST implement + * all of these functions. + */ +typedef struct pjmedia_vid_codec_op +{ + /** + * Initialize codec using the specified attribute. + * + * Application should call #pjmedia_vid_codec_init() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param pool Pool to use when the codec needs to allocate + * some memory. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*init)(pjmedia_vid_codec *codec, + pj_pool_t *pool ); + + /** + * Open the codec and initialize with the specified parameter. + * Upon successful initialization, the codec may modify the parameter + * and fills in the unspecified values (such as size or frame rate of + * the encoder format, as it may need to be negotiated with remote + * preferences via SDP fmtp). + * + * Application should call #pjmedia_vid_codec_open() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param param Codec initialization parameter. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*open)(pjmedia_vid_codec *codec, + pjmedia_vid_codec_param *param ); + + /** + * Close and shutdown codec, releasing all resources allocated by + * this codec, if any. + * + * Application should call #pjmedia_vid_codec_close() instead of + * calling this function directly. + * + * @param codec The codec instance. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*close)(pjmedia_vid_codec *codec); + + /** + * Modify the codec parameter after the codec is open. + * Note that not all codec parameters can be modified during run-time. + * When the parameter cannot be changed, this function will return + * non-PJ_SUCCESS, and the original parameters will not be changed. + * + * Application should call #pjmedia_vid_codec_modify() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param param The new codec parameter. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*modify)(pjmedia_vid_codec *codec, + const pjmedia_vid_codec_param *param); + + /** + * Get the codec parameter after the codec is opened. + * + * Application should call #pjmedia_vid_codec_get_param() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param param The codec parameter. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*get_param)(pjmedia_vid_codec *codec, + pjmedia_vid_codec_param *param); + + /** + * Instruct the codec to generate a payload/packet from a picture + * bitstream to be sent (via network). The maximum payload size or + * MTU is configurable via enc_mtu field of #pjmedia_vid_codec_param. + * For a long bitstream, application usually need to call this function + * multiple times until the whole bitstream is sent. Note that, for + * performance reason, the packetization will be done in-place, so the + * original bitstream may be modified by this function. + * + * Application should call #pjmedia_vid_codec_packetize() instead of + * calling this function directly. + * + * @param codec The codec instance + * @param bits The picture bitstream. + * @param bits_len The length of the bitstream. + * @param bits_pos On input, the start position of the bitstream + * to be packetized. On output, the next position for + * next packet. + * @param pkt The pointer of the generated payload. + * @param pkt_len The payload length. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*packetize) (pjmedia_vid_codec *codec, + pj_uint8_t *bits, + pj_size_t bits_len, + unsigned *bits_pos, + const pj_uint8_t **pkt, + pj_size_t *pkt_len); + + /** + * Instruct the codec to parse a payload and append it into a picture + * bitstream. A picture bitstreams may need to be reconstructed from + * one or more payloads. Note that this function will not provide the + * detection of picture boundary, so application should manage the + * picture boundary detection by itself, e.g: for RTP delivery, payloads + * belong to the same picture will share the same RTP timestamp and also + * there is marker bit in the RTP header that is usually reserved for + * end-of-picture flag. Also note that in case of noticing packet lost, + * application should keep calling this function with payload pointer + * set to NULL, as the packetizer need to update its internal state. + * + * Application should call #pjmedia_vid_codec_unpacketize() instead of + * calling this function directly. + * + * @param codec The codec instance + * @param pkt The input packet. + * @param pkt_size Size of the packet. + * @param timestamp The timestamp of the first sample in the packet. + * @param frame_cnt On input, specifies the maximum number of frames + * in the array. On output, the codec must fill + * with number of frames detected in the packet. + * @param frames On output, specifies the frames that have been + * detected in the packet. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*unpacketize)(pjmedia_vid_codec *codec, + const pj_uint8_t *payload, + pj_size_t payload_len, + pj_uint8_t *bits, + pj_size_t bits_len, + unsigned *bits_pos); + + /** + * Instruct the codec to encode the specified input frame. The input + * MUST contain only one picture with appropriate format as specified + * in opening the codec. + * + * Application should call #pjmedia_vid_codec_encode() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param input The input frame. + * @param out_size The length of buffer in the output frame. + * @param output The output frame. + * + * @return PJ_SUCCESS on success; + */ + pj_status_t (*encode)(pjmedia_vid_codec *codec, + const pjmedia_frame *input, + unsigned out_size, + pjmedia_frame *output); + + /** + * Instruct the codec to decode the specified input frame. The input + * frame MUST contain exactly one picture. Note that the decoded picture + * format may different to the current setting, e.g: the format specified + * in the #pjmedia_vid_codec_param when opening the codec, in this case the + * PJMEDIA_EVENT_FMT_CHANGED event will be emitted by the codec. The codec + * parameter will also be updated, and application can query the format by + * using #get_param(). + * + * Application should call #pjmedia_vid_codec_decode() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param input The input frame. + * @param out_size The length of buffer in the output frame. + * @param output The output frame. + * + * @return PJ_SUCCESS on success; + */ + pj_status_t (*decode)(pjmedia_vid_codec *codec, + const pjmedia_frame *input, + unsigned out_size, + pjmedia_frame *output); + + /** + * Instruct the codec to recover a missing frame. + * + * Application should call #pjmedia_vid_codec_recover() instead of + * calling this function directly. + * + * @param codec The codec instance. + * @param out_size The length of buffer in the output frame. + * @param output The output frame where generated signal + * will be placed. + * + * @return PJ_SUCCESS on success; + */ + pj_status_t (*recover)(pjmedia_vid_codec *codec, + unsigned out_size, + pjmedia_frame *output); + +} pjmedia_vid_codec_op; + + + +/* + * Forward declaration for pjmedia_vid_codec_factory. + */ +typedef struct pjmedia_vid_codec_factory pjmedia_vid_codec_factory; + + +/** + * This structure describes a video codec instance. Codec implementers + * should use #pjmedia_vid_codec_init() to initialize this structure with + * default values. + */ +struct pjmedia_vid_codec +{ + /** Entries to put this codec instance in codec factory's list. */ + PJ_DECL_LIST_MEMBER(struct pjmedia_vid_codec); + + /** Codec's private data. */ + void *codec_data; + + /** Codec factory where this codec was allocated. */ + pjmedia_vid_codec_factory *factory; + + /** Operations to codec. */ + pjmedia_vid_codec_op *op; + + /** Event publisher object */ + pjmedia_event_publisher epub; +}; + + + +/** + * This structure describes operations that must be supported by codec + * factories. + */ +typedef struct pjmedia_vid_codec_factory_op +{ + /** + * Check whether the factory can create codec with the specified + * codec info. + * + * @param factory The codec factory. + * @param info The codec info. + * + * @return PJ_SUCCESS if this factory is able to create an + * instance of codec with the specified info. + */ + pj_status_t (*test_alloc)(pjmedia_vid_codec_factory *factory, + const pjmedia_vid_codec_info *info ); + + /** + * Create default attributes for the specified codec ID. This function + * can be called by application to get the capability of the codec. + * + * @param factory The codec factory. + * @param info The codec info. + * @param attr The attribute to be initialized. + * + * @return PJ_SUCCESS if success. + */ + pj_status_t (*default_attr)(pjmedia_vid_codec_factory *factory, + const pjmedia_vid_codec_info *info, + pjmedia_vid_codec_param *attr ); + + /** + * Enumerate supported codecs that can be created using this factory. + * + * @param factory The codec factory. + * @param count On input, specifies the number of elements in + * the array. On output, the value will be set to + * the number of elements that have been initialized + * by this function. + * @param info The codec info array, which contents will be + * initialized upon return. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*enum_info)(pjmedia_vid_codec_factory *factory, + unsigned *count, + pjmedia_vid_codec_info codecs[]); + + /** + * Create one instance of the codec with the specified codec info. + * + * @param factory The codec factory. + * @param info The codec info. + * @param p_codec Pointer to receive the codec instance. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*alloc_codec)(pjmedia_vid_codec_factory *factory, + const pjmedia_vid_codec_info *info, + pjmedia_vid_codec **p_codec); + + /** + * This function is called by codec manager to return a particular + * instance of codec back to the codec factory. + * + * @param factory The codec factory. + * @param codec The codec instance to be returned. + * + * @return PJ_SUCCESS on success. + */ + pj_status_t (*dealloc_codec)(pjmedia_vid_codec_factory *factory, + pjmedia_vid_codec *codec ); + +} pjmedia_vid_codec_factory_op; + + + +/** + * Codec factory describes a module that is able to create codec with specific + * capabilities. These capabilities can be queried by codec manager to create + * instances of codec. + */ +struct pjmedia_vid_codec_factory +{ + /** Entries to put this structure in the codec manager list. */ + PJ_DECL_LIST_MEMBER(struct pjmedia_vid_codec_factory); + + /** The factory's private data. */ + void *factory_data; + + /** Operations to the factory. */ + pjmedia_vid_codec_factory_op *op; + +}; + + +/** + * Opaque declaration for codec manager. + */ +typedef struct pjmedia_vid_codec_mgr pjmedia_vid_codec_mgr; + +/** + * Declare maximum codecs + */ +#define PJMEDIA_VID_CODEC_MGR_MAX_CODECS 32 + + +/** + * Initialize pjmedia_vid_codec structure with default values. + * + * @param codec The codec to be initialized. + * @param sig Codec's object signature (see signatures.h) + */ +PJ_DECL(void) pjmedia_vid_codec_reset(pjmedia_vid_codec *codec, + pjmedia_obj_sig sig); + +/** + * Initialize codec manager. If there is no the default video codec manager, + * this function will automatically set the default video codec manager to + * the new codec manager instance. Normally this function is called by pjmedia + * endpoint's initialization code. + * + * @param pool The pool instance. + * @param mgr The pointer to the new codec manager instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_mgr_create(pj_pool_t *pool, + pjmedia_vid_codec_mgr **mgr); + + +/** + * Destroy codec manager. Normally this function is called by pjmedia + * endpoint's deinitialization code. + * + * @param mgr Codec manager instance. If NULL, it is the default codec + * manager instance will be destroyed. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_mgr_destroy(pjmedia_vid_codec_mgr *mgr); + + +/** + * Get the default codec manager instance. + * + * @return The default codec manager instance or NULL if none. + */ +PJ_DECL(pjmedia_vid_codec_mgr*) pjmedia_vid_codec_mgr_instance(void); + + +/** + * Set the default codec manager instance. + * + * @param mgr The codec manager instance. + */ +PJ_DECL(void) pjmedia_vid_codec_mgr_set_instance(pjmedia_vid_codec_mgr* mgr); + + +/** + * Register codec factory to codec manager. This will also register + * all supported codecs in the factory to the codec manager. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param factory The codec factory to be registered. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_register_factory( pjmedia_vid_codec_mgr *mgr, + pjmedia_vid_codec_factory *factory); + +/** + * Unregister codec factory from the codec manager. This will also + * remove all the codecs registered by the codec factory from the + * codec manager's list of supported codecs. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param factory The codec factory to be unregistered. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_unregister_factory( pjmedia_vid_codec_mgr *mgr, + pjmedia_vid_codec_factory *factory); + +/** + * Enumerate all supported codecs that have been registered to the + * codec manager by codec factories. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param count On input, specifies the number of elements in + * the array. On output, the value will be set to + * the number of elements that have been initialized + * by this function. + * @param info The codec info array, which contents will be + * initialized upon return. + * @param prio Optional pointer to receive array of codec priorities. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_mgr_enum_codecs( + pjmedia_vid_codec_mgr *mgr, + unsigned *count, + pjmedia_vid_codec_info info[], + unsigned *prio); + + +/** + * Get codec info for the specified payload type. The payload type must be + * static or locally defined in #pjmedia_video_pt. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param pt The payload type/number. + * @param info Pointer to receive codec info. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_get_codec_info( pjmedia_vid_codec_mgr *mgr, + unsigned pt, + const pjmedia_vid_codec_info **info); + + +/** + * Get codec info for the specified format ID. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param fmt_id Format ID. See #pjmedia_format_id + * @param info Pointer to receive codec info. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_get_codec_info2(pjmedia_vid_codec_mgr *mgr, + pjmedia_format_id fmt_id, + const pjmedia_vid_codec_info **info); + + +/** + * Convert codec info struct into a unique codec identifier. + * A codec identifier looks something like "H263/90000". + * + * @param info The codec info + * @param id Buffer to put the codec info string. + * @param max_len The length of the buffer. + * + * @return The null terminated codec info string, or NULL if + * the buffer is not long enough. + */ +PJ_DECL(char*) pjmedia_vid_codec_info_to_id( + const pjmedia_vid_codec_info *info, + char *id, unsigned max_len ); + + +/** + * Find codecs by the unique codec identifier. This function will find + * all codecs that match the codec identifier prefix. For example, if + * "H26" is specified, then it will find "H263/90000", "H264/90000", + * and so on, up to the maximum count specified in the argument. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param codec_id The full codec ID or codec ID prefix. If an empty + * string is given, it will match all codecs. + * @param count Maximum number of codecs to find. On return, it + * contains the actual number of codecs found. + * @param p_info Array of pointer to codec info to be filled. This + * argument may be NULL, which in this case, only + * codec count will be returned. + * @param prio Optional array of codec priorities. + * + * @return PJ_SUCCESS if at least one codec info is found. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_find_codecs_by_id(pjmedia_vid_codec_mgr *mgr, + const pj_str_t *codec_id, + unsigned *count, + const pjmedia_vid_codec_info *p_info[], + unsigned prio[]); + + +/** + * Set codec priority. The codec priority determines the order of + * the codec in the SDP created by the endpoint. If more than one codecs + * are found with the same codec_id prefix, then the function sets the + * priorities of all those codecs. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param codec_id The full codec ID or codec ID prefix. If an empty + * string is given, it will match all codecs. + * @param prio Priority to be set. The priority can have any value + * between 1 to 255. When the priority is set to zero, + * the codec will be disabled. + * + * @return PJ_SUCCESS if at least one codec info is found. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_set_codec_priority(pjmedia_vid_codec_mgr *mgr, + const pj_str_t *codec_id, + pj_uint8_t prio); + + +/** + * Get default codec param for the specified codec info. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param info The codec info, which default parameter's is being + * queried. + * @param param On return, will be filled with the default codec + * parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_get_default_param(pjmedia_vid_codec_mgr *mgr, + const pjmedia_vid_codec_info *info, + pjmedia_vid_codec_param *param); + + +/** + * Set default codec param for the specified codec info. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param pool The pool instance. + * @param info The codec info, which default parameter's is being + * updated. + * @param param The new default codec parameter. Set to NULL to reset + * codec parameter to library default settings. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_set_default_param(pjmedia_vid_codec_mgr *mgr, + pj_pool_t *pool, + const pjmedia_vid_codec_info *info, + const pjmedia_vid_codec_param *param); + + +/** + * Request the codec manager to allocate one instance of codec with the + * specified codec info. The codec will enumerate all codec factories + * until it finds factory that is able to create the specified codec. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param info The information about the codec to be created. + * @param p_codec Pointer to receive the codec instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_codec_mgr_alloc_codec( pjmedia_vid_codec_mgr *mgr, + const pjmedia_vid_codec_info *info, + pjmedia_vid_codec **p_codec); + +/** + * Deallocate the specified codec instance. The codec manager will return + * the instance of the codec back to its factory. + * + * @param mgr The codec manager instance. If NULL, the default codec + * manager instance will be used. + * @param codec The codec instance. + * + * @return PJ_SUCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_mgr_dealloc_codec( + pjmedia_vid_codec_mgr *mgr, + pjmedia_vid_codec *codec); + + + +/** + * Initialize codec using the specified attribute. + * + * @param codec The codec instance. + * @param pool Pool to use when the codec needs to allocate + * some memory. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_init( pjmedia_vid_codec *codec, + pj_pool_t *pool ) +{ + return (*codec->op->init)(codec, pool); +} + + +/** + * Open the codec and initialize with the specified parameter. + * Upon successful initialization, the codec may modify the parameter + * and fills in the unspecified values (such as size or frame rate of + * the encoder format, as it may need to be negotiated with remote + * preferences via SDP fmtp). + * + * @param codec The codec instance. + * @param param Codec initialization parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_open( + pjmedia_vid_codec *codec, + pjmedia_vid_codec_param *param ) +{ + return (*codec->op->open)(codec, param); +} + + +/** + * Close and shutdown codec, releasing all resources allocated by + * this codec, if any. + * + * @param codec The codec instance. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_close( pjmedia_vid_codec *codec ) +{ + return (*codec->op->close)(codec); +} + + +/** + * Modify the codec parameter after the codec is open. + * Note that not all codec parameters can be modified during run-time. + * When the parameter cannot be changed, this function will return + * non-PJ_SUCCESS, and the original parameters will not be changed. + * + * @param codec The codec instance. + * @param param The new codec parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_modify( + pjmedia_vid_codec *codec, + const pjmedia_vid_codec_param *param) +{ + return (*codec->op->modify)(codec, param); +} + + +/** + * Get the codec parameter after the codec is opened. + * + * @param codec The codec instance. + * @param param The codec parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_get_param( + pjmedia_vid_codec *codec, + pjmedia_vid_codec_param *param) +{ + return (*codec->op->get_param)(codec, param); +} + + +/** + * Instruct the codec to generate a payload/packet from a picture + * bitstream to be sent (via network). The maximum payload size or + * MTU is configurable via enc_mtu field of #pjmedia_vid_codec_param. + * For a long bitstream, application usually need to call this function + * multiple times until the whole bitstream is sent. Note that, for + * performance reason, the packetization will be done in-place, so the + * original bitstream may be modified by this function. + * + * @param codec The codec instance + * @param bits The picture bitstream. + * @param bits_len The length of the bitstream. + * @param bits_pos On input, the start position of the bitstream + * to be packetized. On output, the next position for + * next packet. + * @param pkt The pointer of the generated payload. + * @param pkt_len The payload length. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_packetize( + pjmedia_vid_codec *codec, + pj_uint8_t *bits, + pj_size_t bits_len, + unsigned *bits_pos, + const pj_uint8_t **pkt, + pj_size_t *pkt_len ) +{ + return (*codec->op->packetize)(codec, bits, bits_len, bits_pos, + pkt, pkt_len); +} + + +/** + * Instruct the codec to parse a payload and append it into a picture + * bitstream. A picture bitstreams may need to be reconstructed from + * one or more payloads. Note that this function will not provide the + * detection of picture boundary, so application should manage the + * picture boundary detection by itself, e.g: for RTP delivery, payloads + * belong to the same picture will share the same RTP timestamp and also + * there is marker bit in the RTP header that is usually reserved for + * end-of-picture flag. Also note that in case of noticing packet lost, + * application should keep calling this function with payload pointer + * set to NULL, as the packetizer need to update its internal state. + * + * @param codec The codec instance + * @param pkt The input packet. + * @param pkt_size Size of the packet. + * @param timestamp The timestamp of the first sample in the packet. + * @param frame_cnt On input, specifies the maximum number of frames + * in the array. On output, the codec must fill + * with number of frames detected in the packet. + * @param frames On output, specifies the frames that have been + * detected in the packet. + * + * @return PJ_SUCCESS on success. + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_unpacketize( + pjmedia_vid_codec *codec, + const pj_uint8_t *payload, + pj_size_t payload_len, + pj_uint8_t *bits, + pj_size_t bits_len, + unsigned *bits_pos ) +{ + return (*codec->op->unpacketize)(codec, payload, payload_len, bits, + bits_len, bits_pos); +} + + +/** + * Instruct the codec to encode the specified input frame. The input + * MUST contain only one picture with appropriate format as specified + * in opening the codec. + * + * @param codec The codec instance. + * @param input The input frame. + * @param out_size The length of buffer in the output frame. + * @param output The output frame. + * + * @return PJ_SUCCESS on success; + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_encode( + pjmedia_vid_codec *codec, + const pjmedia_frame *input, + unsigned out_size, + pjmedia_frame *output) +{ + return (*codec->op->encode)(codec, input, out_size, output); +} + + +/** + * Instruct the codec to decode the specified input frame. The input + * frame MUST contain exactly one picture. Note that the decoded picture + * format may different to the current setting, e.g: the format specified + * in the #pjmedia_vid_codec_param when opening the codec, in this case the + * PJMEDIA_EVENT_FMT_CHANGED event will be emitted by the codec. The codec + * parameter will also be updated, and application can query the format by + * using #get_param(). + * + * @param codec The codec instance. + * @param input The input frame. + * @param out_size The length of buffer in the output frame. + * @param output The output frame. + * + * @return PJ_SUCCESS on success; + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_decode( + pjmedia_vid_codec *codec, + const pjmedia_frame *input, + unsigned out_size, + pjmedia_frame *output) +{ + return (*codec->op->decode)(codec, input, out_size, output); +} + + +/** + * Instruct the codec to recover a missing frame. + * + * @param codec The codec instance. + * @param out_size The length of buffer in the output frame. + * @param output The output frame where generated signal + * will be placed. + * + * @return PJ_SUCCESS on success; + */ +PJ_INLINE(pj_status_t) pjmedia_vid_codec_recover( + pjmedia_vid_codec *codec, + unsigned out_size, + pjmedia_frame *output) +{ + if (codec->op && codec->op->recover) + return (*codec->op->recover)(codec, out_size, output); + else + return PJ_ENOTSUP; +} + + +/** + * @} + */ + +/** + * @defgroup PJMEDIA_CODEC_VID_CODECS Supported video codecs + * @ingroup PJMEDIA_CODEC + * @brief Documentation about individual video codec supported by PJMEDIA + * @{ + * Please see the APIs provided by the individual codecs below. + */ +/** + * @} + */ + + + + +PJ_END_DECL + + +#endif /* __PJMEDIA_VID_CODEC_H__ */ diff --git a/pjmedia/include/pjmedia/vid_codec_util.h b/pjmedia/include/pjmedia/vid_codec_util.h new file mode 100644 index 00000000..e34440a4 --- /dev/null +++ b/pjmedia/include/pjmedia/vid_codec_util.h @@ -0,0 +1,158 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com) + * Copyright (C) 2003-2008 Benny Prijono + * + * 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_VID_CODEC_UTIL_H__ +#define __PJMEDIA_VID_CODEC_UTIL_H__ + + +/** + * @file vid_codec_util.h + * @brief Video codec utilities. + */ + +#include +#include + +PJ_BEGIN_DECL + + +/** + * Definition of H.263 parameters. + */ +typedef struct pjmedia_vid_codec_h263_fmtp +{ + unsigned mpi_cnt; /**< # of parsed MPI param */ + struct mpi { + pjmedia_rect_size size; /**< Picture size/resolution */ + unsigned val; /**< MPI value */ + } mpi[32]; /**< Minimum Picture Interval parameter */ + +} pjmedia_vid_codec_h263_fmtp; + + +/** + * Parse SDP fmtp of H.263. + * + * @param fmtp The H.263 SDP fmtp to be parsed. + * @param h263_fmtp The parsing result. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_h263_parse_fmtp( + const pjmedia_codec_fmtp *fmtp, + pjmedia_vid_codec_h263_fmtp *h263_fmtp); + + +/** + * Parse, negotiate, and apply the encoding and decoding SDP fmtp of H.263 + * in the specified codec parameter. + * + * @param param The codec parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_h263_apply_fmtp( + pjmedia_vid_codec_param *param); + + +/** + * Definition of H.264 parameters. + */ +typedef struct pjmedia_vid_codec_h264_fmtp +{ + /* profile-level-id */ + pj_uint8_t profile_idc; /**< Profile ID */ + pj_uint8_t profile_iop; /**< Profile constraints bits */ + pj_uint8_t level; /**< Level */ + + /* packetization-mode */ + pj_uint8_t packetization_mode; /**< Packetization mode */ + + /* max-mbps, max-fs, max-cpb, max-dpb, and max-br */ + unsigned max_mbps; /**< Max macroblock processing rate */ + unsigned max_fs; /**< Max frame size (in macroblocks) */ + unsigned max_cpb; /**< Max coded picture buffer size */ + unsigned max_dpb; /**< Max decoded picture buffer size */ + unsigned max_br; /**< Max video bit rate */ + + /* sprop-parameter-sets, in NAL units */ + pj_size_t sprop_param_sets_len; /**< Parameter set length */ + pj_uint8_t sprop_param_sets[256]; /**< Parameter set (SPS & PPS), + in NAL unit bitstream */ + +} pjmedia_vid_codec_h264_fmtp; + + +/** + * Parse SDP fmtp of H.264. + * + * @param fmtp The H.264 SDP fmtp to be parsed. + * @param h264_fmtp The parsing result. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_h264_parse_fmtp( + const pjmedia_codec_fmtp *fmtp, + pjmedia_vid_codec_h264_fmtp *h264_fmtp); + + +/** + * Match H.264 format in the SDP media offer and answer. This will compare + * H.264 identifier parameters in SDP fmtp, i.e: "profile-level-id" and + * "packetization-mode" fields. For better interoperability, when the option + * #PJMEDIA_SDP_NEG_FMT_MATCH_ALLOW_MODIFY_ANSWER is set, this function + * may update the answer so the parameters in the answer match to ones + * in the offer. + * + * @param pool The memory pool. + * @param offer The SDP media offer. + * @param o_fmt_idx Index of the H.264 format in the SDP media offer. + * @param answer The SDP media answer. + * @param a_fmt_idx Index of the H.264 format in the SDP media answer. + * @param option The format matching option, see + * #pjmedia_sdp_neg_fmt_match_flag. + * + * @return PJ_SUCCESS when the formats in offer and answer match. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_h264_match_sdp( + pj_pool_t *pool, + pjmedia_sdp_media *offer, + unsigned o_fmt_idx, + pjmedia_sdp_media *answer, + unsigned a_fmt_idx, + unsigned option); + + +/** + * Parse and apply the encoding and decoding SDP fmtp of H.264 in the + * specified codec parameter. This will validate size and fps to conform + * to H.264 level specified in SDP fmtp "profile-level-id". + * + * @param param The codec parameter. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_codec_h264_apply_fmtp( + pjmedia_vid_codec_param *param); + + +PJ_END_DECL + + +#endif /* __PJMEDIA_VID_CODEC_UTIL_H__ */ diff --git a/pjmedia/include/pjmedia/vid_port.h b/pjmedia/include/pjmedia/vid_port.h new file mode 100644 index 00000000..692a4f9d --- /dev/null +++ b/pjmedia/include/pjmedia/vid_port.h @@ -0,0 +1,241 @@ +/* $Id$ */ +/* + * Copyright (C) 2008-2010 Teluu Inc. (http://www.teluu.com) + * + * 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_VIDPORT_H__ +#define __PJMEDIA_VIDPORT_H__ + +/** + * @file pjmedia/videoport.h Video media port + * @brief Video media port + */ + +#include +#include + +/** + * @defgroup PJMEDIA_VIDEO_PORT Video media port + * @ingroup PJMEDIA_PORT_CLOCK + * @brief Video media port + * @{ + */ + +PJ_BEGIN_DECL + +/** + * This structure describes the parameters to create a video port + */ +typedef struct pjmedia_vid_port_param +{ + /** + * Video stream parameter. + */ + pjmedia_vid_dev_param vidparam; + + /** + * Specify whether the video port should use active or passive interface. + * If active interface is selected, the video port will perform as + * a media clock, automatically calls pjmedia_port_get_frame() and + * pjmedia_port_put_frame() of its slave port (depending on the direction + * that is specified when opening the video stream). If passive interface + * is selected, application can retrieve the media port of this video + * port by calling pjmedia_vid_port_get_passive_port(), and subsequently + * calls pjmedia_port_put_frame() or pjmedia_port_get_frame() to that + * media port. + * + * Default: PJ_TRUE + */ + pj_bool_t active; + +} pjmedia_vid_port_param; + +/** + * Opaque data type for video port. + */ +typedef struct pjmedia_vid_port pjmedia_vid_port; + +/** + * Initialize the parameter with the default values. Note that this typically + * would only fill the structure to zeroes unless they have different default + * values. + * + * @param prm The parameter. + */ +PJ_DECL(void) pjmedia_vid_port_param_default(pjmedia_vid_port_param *prm); + +/** + * Create a video port with the specified parameter. + * + * @param pool Pool to allocate memory from. + * @param prm The video port parameter. + * @param p_vp Pointer to receive the result. + * + * @return PJ_SUCCESS if video port has been created + * successfully, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_port_create(pj_pool_t *pool, + const pjmedia_vid_port_param *prm, + pjmedia_vid_port **p_vp); + +/** + * Set the callbacks of the video port's underlying video stream. + * + * @param vid_port The video port. + * @param cb Pointer to structure containing video stream + * callbacks. + * @param user_data Arbitrary user data, which will be given back in the + * callbacks. + */ +PJ_DECL(void) pjmedia_vid_port_set_cb(pjmedia_vid_port *vid_port, + const pjmedia_vid_dev_cb *cb, + void *user_data); + +/** + * Get the event publisher instance of the video port. + * + * @param vid_port The video port. + * + * @return The event publisher of the video port. + */ +PJ_DECL(pjmedia_event_publisher*) +pjmedia_vid_port_get_event_publisher(pjmedia_vid_port *vid_port); + +/** + * Return the underlying video stream of the video port. + * + * @param vid_port The video port. + * + * @return The video stream. + */ +PJ_DECL(pjmedia_vid_dev_stream*) +pjmedia_vid_port_get_stream(pjmedia_vid_port *vid_port); + +/** + * Return the (passive) media port of the video port. This operation + * is only valid for video ports created with passive interface selected. + * Retrieving the media port for active video ports may raise an + * assertion. + * + * @param vid_port The video port. + * + * @return The media port instance, or NULL. + */ +PJ_DECL(pjmedia_port*) +pjmedia_vid_port_get_passive_port(pjmedia_vid_port *vid_port); + +/** + * Get a clock source from the video port. + * + * @param vid_port The video port. + * + * @return The clock source. + */ +PJ_DECL(pjmedia_clock_src *) +pjmedia_vid_port_get_clock_src( pjmedia_vid_port *vid_port ); + +/** + * Set a clock source for the video port. + * + * @param vid_port The video port. + * @param clocksrc The clock source. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_port_set_clock_src( pjmedia_vid_port *vid_port, + pjmedia_clock_src *clocksrc ); + +/** + * Connect the video port to a downstream (slave) media port. This operation + * is only valid for video ports created with active interface selected. + * Connecting a passive video port may raise an assertion. + * + * @param vid_port The video port. + * @param port A downstream media port to be connected to + * this video port. + * @param destroy Specify if the downstream media port should also be + * destroyed by this video port when the video port + * is destroyed. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_port_connect(pjmedia_vid_port *vid_port, + pjmedia_port *port, + pj_bool_t destroy); + +/** + * Disconnect the video port from its downstream (slave) media port, if any. + * This operation is only valid for video ports created with active interface + * selected, and assertion may be triggered if this is invoked on a passive + * video port. + * + * @param vid_port The video port. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_port_disconnect(pjmedia_vid_port *vid_port); + +/** + * Retrieve the media port currently connected as downstream media port of the + * specified video port. This operation is only valid for video ports created + * with active interface selected, and assertion may be triggered if this is + * invoked on a passive video port. + * + * @param vid_port The video port. + * + * @return Media port currently connected to the video port, + * if any. + */ +PJ_DECL(pjmedia_port*) +pjmedia_vid_port_get_connected_port(pjmedia_vid_port *vid_port); + +/** + * Start the video port. + * + * @param vid_port The video port. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_port_start(pjmedia_vid_port *vid_port); + +/** + * Stop the video port. + * + * @param vid_port The video port. + * + * @return PJ_SUCCESS on success or the appropriate error code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_port_stop(pjmedia_vid_port *vid_port); + +/** + * Destroy the video port, along with its video stream. If the video port is + * an active one, this may also destroy the downstream media port, if the + * destroy flag is set when the media port is connected. + * + * @param vid_port The video port. + */ +PJ_DECL(void) pjmedia_vid_port_destroy(pjmedia_vid_port *vid_port); + + +PJ_END_DECL + +/** + * @} + */ + +#endif /* __PJMEDIA_VIDPORT_H__ */ + diff --git a/pjmedia/include/pjmedia/vid_stream.h b/pjmedia/include/pjmedia/vid_stream.h new file mode 100644 index 00000000..83df1167 --- /dev/null +++ b/pjmedia/include/pjmedia/vid_stream.h @@ -0,0 +1,319 @@ +/* $Id$ */ +/* + * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) + * + * 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_VID_STREAM_H__ +#define __PJMEDIA_VID_STREAM_H__ + + +/** + * @file vid_stream.h + * @brief Video Stream. + */ + +#include +#include +#include +#include +#include +#include +#include + +PJ_BEGIN_DECL + + +/** + * @defgroup PJMED_VID_STRM Video streams + * @ingroup PJMEDIA_PORT + * @brief Video communication via the network + * @{ + * + * A video stream is a bidirectional video communication between two + * endpoints. It corresponds to a video media description ("m=video" line) + * in SDP session descriptor. + * + * A video stream consists of two unidirectional channels: + * - encoding channel, which transmits unidirectional video to remote, and + * - decoding channel, which receives unidirectional media from remote. + * + * A video stream exports two media port interface (see @ref PJMEDIA_PORT), + * one for each direction, and application normally uses this interface to + * interconnect the stream to other PJMEDIA components, e.g: the video + * capture port supplies frames to the encoding port and video renderer + * consumes frames from the decoding port. + * + * A video stream internally manages the following objects: + * - an instance of video codec (see @ref PJMEDIA_VID_CODEC), + * - an @ref PJMED_JBUF, + * - two instances of RTP sessions (#pjmedia_rtp_session, one for each + * direction), + * - one instance of RTCP session (#pjmedia_rtcp_session), + * - and a reference to video transport to send and receive packets + * to/from the network (see @ref PJMEDIA_TRANSPORT). + * + * Video streams are created by calling #pjmedia_vid_stream_create(), + * specifying #pjmedia_stream_info structure in the parameter. Application + * can construct the #pjmedia_vid_stream_info structure manually, or use + * #pjmedia_vid_stream_info_from_sdp() function to construct the + * #pjmedia_vid stream_info from local and remote SDP session descriptors. + */ + + +/** + * This structure describes video stream information. Each video stream + * corresponds to one "m=" line in SDP session descriptor, and it has + * its own RTP/RTCP socket pair. + */ +typedef struct pjmedia_vid_stream_info +{ + pjmedia_type type; /**< Media type (audio, video) */ + pjmedia_tp_proto proto; /**< Transport protocol (RTP/AVP, etc.) */ + pjmedia_dir dir; /**< Media direction. */ + pj_sockaddr rem_addr; /**< Remote RTP address */ + pj_sockaddr rem_rtcp; /**< Optional remote RTCP address. If + sin_family is zero, the RTP address + will be calculated from RTP. */ + unsigned tx_pt; /**< Outgoing codec paylaod type. */ + unsigned rx_pt; /**< Incoming codec paylaod type. */ + pj_uint32_t ssrc; /**< RTP SSRC. */ + pj_uint32_t rtp_ts; /**< Initial RTP timestamp. */ + pj_uint16_t rtp_seq; /**< Initial RTP sequence number. */ + pj_uint8_t rtp_seq_ts_set; + /**< Bitmask flags if initial RTP sequence + and/or timestamp for sender are set. + bit 0/LSB : sequence flag + bit 1 : timestamp flag */ + int jb_init; /**< Jitter buffer init delay in msec. + (-1 for default). */ + int jb_min_pre; /**< Jitter buffer minimum prefetch + delay in msec (-1 for default). */ + int jb_max_pre; /**< Jitter buffer maximum prefetch + delay in msec (-1 for default). */ + int jb_max; /**< Jitter buffer max delay in msec. */ + +#if defined(PJMEDIA_STREAM_ENABLE_KA) && PJMEDIA_STREAM_ENABLE_KA!=0 + pj_bool_t use_ka; /**< Stream keep-alive and NAT hole punch + (see #PJMEDIA_STREAM_ENABLE_KA) + is enabled? */ +#endif + + pjmedia_vid_codec_info codec_info; /**< Incoming codec format info. */ + pjmedia_vid_codec_param *codec_param; /**< Optional codec param. */ + +} pjmedia_vid_stream_info; + + +/** + * This function will initialize the video stream info based on information + * in both SDP session descriptors for the specified stream index. + * The remaining information will be taken from default codec parameters. + * If socket info array is specified, the socket will be copied to the + * session info as well. + * + * @param si Stream info structure to be initialized. + * @param pool Pool to allocate memory. + * @param endpt PJMEDIA endpoint instance. + * @param local Local SDP session descriptor. + * @param remote Remote SDP session descriptor. + * @param stream_idx Media stream index in the session descriptor. + * + * @return PJ_SUCCESS if stream info is successfully initialized. + */ +PJ_DECL(pj_status_t) +pjmedia_vid_stream_info_from_sdp(pjmedia_vid_stream_info *si, + pj_pool_t *pool, + pjmedia_endpt *endpt, + const pjmedia_sdp_session *local, + const pjmedia_sdp_session *remote, + unsigned stream_idx); + + +/* + * Opaque declaration for video stream. + */ +typedef struct pjmedia_vid_stream pjmedia_vid_stream; + + +/** + * Create a video stream based on the specified parameter. After the video + * stream has been created, application normally would want to get the media + * port interface of the stream, by calling pjmedia_vid_stream_get_port(). + * The media port interface exports put_frame() and get_frame() function, + * used to transmit and receive media frames from the stream. + * + * Without application calling put_frame() and get_frame(), there will be + * no media frames transmitted or received by the stream. + * + * @param endpt Media endpoint. + * @param pool Optional pool to allocate memory for the stream. If + * this is not specified, one will be created internally. + * A large number of memory may be needed because jitter + * buffer needs to preallocate some storage. + * @param info Stream information to create the stream. Upon return, + * this info will be updated with the information from + * the instantiated codec. Note that if the "pool" + * argument is NULL, some fields in this "info" parameter + * will be allocated from the internal pool of the + * stream, which means that they will only remain valid + * as long as the stream is not destroyed. + * @param tp Media transport instance used to transmit and receive + * RTP/RTCP packets to/from the underlying network. + * @param user_data Arbitrary user data (for future callback feature). + * @param p_stream Pointer to receive the video stream. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_create( + pjmedia_endpt *endpt, + pj_pool_t *pool, + pjmedia_vid_stream_info *info, + pjmedia_transport *tp, + void *user_data, + pjmedia_vid_stream **p_stream); + +/** + * Destroy the video stream. + * + * @param stream The video stream. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_destroy(pjmedia_vid_stream *stream); + + +/** + * Get the media port interface of the stream. The media port interface + * declares put_frame() and get_frame() function, which is the only + * way for application to transmit and receive media frames from the + * stream. As bidirectional video streaming may have different video + * formats in the encoding and decoding direction, there are two media + * ports exported by the video stream, one for each direction. + * + * @param stream The video stream. + * @param dir The video direction. + * @param p_port Pointer to receive the port interface. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_get_port( + pjmedia_vid_stream *stream, + pjmedia_dir dir, + pjmedia_port **p_port); + + +/** + * Get the media transport object associated with this stream. + * + * @param st The video stream. + * + * @return The transport object being used by the stream. + */ +PJ_DECL(pjmedia_transport*) pjmedia_vid_stream_get_transport( + pjmedia_vid_stream *st); + + +/** + * Get the stream statistics. See also #pjmedia_stream_get_stat_jbuf() + * + * @param stream The video stream. + * @param stat Media stream statistics. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_get_stat( + const pjmedia_vid_stream *stream, + pjmedia_rtcp_stat *stat); + +/** + * Reset the video stream statistics. + * + * @param stream The video stream. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_reset_stat(pjmedia_vid_stream *stream); + + +/** + * Get current jitter buffer state. See also #pjmedia_stream_get_stat() + * + * @param stream The video stream. + * @param state Jitter buffer state. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_get_stat_jbuf( + const pjmedia_vid_stream *stream, + pjmedia_jb_state *state); + + +/** + * Get the stream info. + * + * @param stream The video stream. + * @param info Video stream info. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_get_info( + const pjmedia_vid_stream *stream, + pjmedia_vid_stream_info *info); + + +/** + * Start the video stream. This will start the appropriate channels + * in the video stream, depending on the video direction that was set + * when the stream was created. + * + * @param stream The video stream. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_start(pjmedia_vid_stream *stream); + + +/** + * Pause the individual channel in the stream. + * + * @param stream The video channel. + * @param dir Which direction to pause. + * + * @return PJ_SUCCESS on success. + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_pause(pjmedia_vid_stream *stream, + pjmedia_dir dir); + +/** + * Resume the individual channel in the stream. + * + * @param stream The video channel. + * @param dir Which direction to resume. + * + * @return PJ_SUCCESS on success; + */ +PJ_DECL(pj_status_t) pjmedia_vid_stream_resume(pjmedia_vid_stream *stream, + pjmedia_dir dir); + + +/** + * @} + */ + +PJ_END_DECL + + +#endif /* __PJMEDIA_VID_STREAM_H__ */ diff --git a/pjmedia/include/pjmedia/vid_tee.h b/pjmedia/include/pjmedia/vid_tee.h new file mode 100644 index 00000000..d9f67796 --- /dev/null +++ b/pjmedia/include/pjmedia/vid_tee.h @@ -0,0 +1,142 @@ +/* $Id$ */ +/* + * Copyright (C) 2011 Teluu Inc. (http://www.teluu.com) + * + * 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_VID_TEE_H__ +#define __PJMEDIA_VID_TEE_H__ + +/** + * @file vid_tee.h + * @brief Video tee (source duplicator). + */ +#include + +/** + * @addtogroup PJMEDIA_VID_TEE Video source duplicator + * @ingroup PJMEDIA_PORT + * @brief Duplicate video data from a media port into multiple media port + * destinations + * @{ + * + * This section describes media port to duplicate video data in the stream. + * + * A video tee branches video stream flow from one source port to multiple + * destination ports by simply duplicating the video data supplied by the + * source port and delivering the copy to all registered destinations. + * + * The video tee is a unidirectional port, i.e: data flows from source port + * to destination ports only. Also, the video source port MUST actively call + * pjmedia_port_put_frame() to the video tee and the video destination ports + * MUST NEVER call pjmedia_port_get_frame() to the video tee. Please note that + * there is no specific order of which destination port will receive a frame + * from the video tee. + * + * The video tee is not thread-safe, so it is application responsibility + * to synchronize video tee operations, e.g: make sure the source port is + * paused during adding or removing a destination port. + */ + +PJ_BEGIN_DECL + + +/** + * Enumeration of video tee flags. + */ +typedef enum pjmedia_vid_tee_flag +{ + /** + * Tell the video tee that the destination port will do in-place + * processing, so the delivered data may be modified by this port. + * If this flag is used, buffer will be copied before being given to + * the destination port. + */ + PJMEDIA_VID_TEE_DST_DO_IN_PLACE_PROC = 4, + +} pjmedia_vid_tee_flag; + + +/** + * Create a video tee port with the specified source media port. Application + * should destroy the tee with pjmedia_port_destroy() as usual. Note that + * destroying the tee does not destroy its destination ports. + * + * @param pool The pool. + * @param fmt The source media port's format. + * @param max_dst_cnt The maximum number of destination ports supported. + * @param p_vid_tee Pointer to receive the video tee port. + * + * @return PJ_SUCCESS on success, or the appropriate + * error code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_tee_create(pj_pool_t *pool, + const pjmedia_format *fmt, + unsigned max_dst_cnt, + pjmedia_port **p_vid_tee); + +/** + * Add a destination media port to the video tee. For this function, the + * destination port's media format must match the source format. + * + * @param vid_tee The video tee. + * @param option Video tee option, see @pjmedia_vid_tee_flag. + * @param port The destination media port. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_tee_add_dst_port(pjmedia_port *vid_tee, + unsigned option, + pjmedia_port *port); + + +/** + * Add a destination media port to the video tee. This function will also + * create a converter if the destination port's media format does not match + * the source format. + * + * @param vid_tee The video tee. + * @param option Video tee option, see @pjmedia_vid_tee_flag. + * @param port The destination media port. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_tee_add_dst_port2(pjmedia_port *vid_tee, + unsigned option, + pjmedia_port *port); + + +/** + * Remove a destination media port from the video tee. + * + * @param vid_tee The video tee. + * @param port The destination media port to be removed. + * + * @return PJ_SUCCESS on success, or the appropriate error + * code. + */ +PJ_DECL(pj_status_t) pjmedia_vid_tee_remove_dst_port(pjmedia_port *vid_tee, + pjmedia_port *port); + + +PJ_END_DECL + +/** + * @} + */ + +#endif /* __PJMEDIA_VID_TEE_H__ */ -- cgit v1.2.3