summaryrefslogtreecommitdiff
path: root/pjmedia/include/pjmedia
diff options
context:
space:
mode:
authorNanang Izzuddin <nanang@teluu.com>2011-07-19 03:42:28 +0000
committerNanang Izzuddin <nanang@teluu.com>2011-07-19 03:42:28 +0000
commitcd283c8825c9a94400f27735acb1c9385e90ffc8 (patch)
tree56d5722310fa8957ce5d1ba7cbd137cf8802dcc7 /pjmedia/include/pjmedia
parented8f8d08abba9040f769e922aa0c1adbde86fbbc (diff)
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
Diffstat (limited to 'pjmedia/include/pjmedia')
-rw-r--r--pjmedia/include/pjmedia/avi.h202
-rw-r--r--pjmedia/include/pjmedia/avi_stream.h170
-rw-r--r--pjmedia/include/pjmedia/circbuf.h1
-rw-r--r--pjmedia/include/pjmedia/clock.h129
-rw-r--r--pjmedia/include/pjmedia/codec.h202
-rw-r--r--pjmedia/include/pjmedia/conference.h6
-rw-r--r--pjmedia/include/pjmedia/config.h162
-rw-r--r--pjmedia/include/pjmedia/converter.h322
-rw-r--r--pjmedia/include/pjmedia/endpoint.h56
-rw-r--r--pjmedia/include/pjmedia/errno.h11
-rw-r--r--pjmedia/include/pjmedia/event.h402
-rw-r--r--pjmedia/include/pjmedia/format.h748
-rw-r--r--pjmedia/include/pjmedia/frame.h332
-rw-r--r--pjmedia/include/pjmedia/jbuf.h113
-rw-r--r--pjmedia/include/pjmedia/port.h205
-rw-r--r--pjmedia/include/pjmedia/sdp.h27
-rw-r--r--pjmedia/include/pjmedia/sdp_neg.h89
-rw-r--r--pjmedia/include/pjmedia/signatures.h217
-rw-r--r--pjmedia/include/pjmedia/sound_port.h14
-rw-r--r--pjmedia/include/pjmedia/stream.h41
-rw-r--r--pjmedia/include/pjmedia/stream_common.h57
-rw-r--r--pjmedia/include/pjmedia/transport.h33
-rw-r--r--pjmedia/include/pjmedia/transport_ice.h24
-rw-r--r--pjmedia/include/pjmedia/types.h448
-rw-r--r--pjmedia/include/pjmedia/vid_codec.h978
-rw-r--r--pjmedia/include/pjmedia/vid_codec_util.h158
-rw-r--r--pjmedia/include/pjmedia/vid_port.h241
-rw-r--r--pjmedia/include/pjmedia/vid_stream.h319
-rw-r--r--pjmedia/include/pjmedia/vid_tee.h142
29 files changed, 5428 insertions, 421 deletions
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 <pjmedia/port.h>
+
+
+
+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 <pj/assert.h>
#include <pj/errno.h>
#include <pj/pool.h>
+#include <pjmedia/frame.h>
/**
* @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 <pjmedia/port.h>
+#include <pj/errno.h>
#include <pj/list.h>
#include <pj/pool.h>
@@ -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
@@ -515,6 +515,15 @@
#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
* and to prevent server from disconnecting the call because no
@@ -568,6 +577,16 @@
/**
+ * 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
* remote, or should it rather use the codec preference as specified by
@@ -592,6 +611,15 @@
/**
+ * 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 <pjmedia/frame.h>
+#include <pjmedia/format.h>
+#include <pj/list.h>
+#include <pj/pool.h>
+
+
+/**
+ * @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 <pjmedia/codec.h>
#include <pjmedia/sdp.h>
+#include <pjmedia/transport.h>
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 <pjmedia/format.h>
+#include <pjmedia/signatures.h>
+#include <pj/list.h>
+
+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 <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJMEDIA_FORMAT_H__
+#define __PJMEDIA_FORMAT_H__
+
+/**
+ * @file pjmedia/format.h Media format
+ * @brief Media format
+ */
+#include <pjmedia/types.h>
+
+/**
+ * @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 <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJMEDIA_FRAME_H__
+#define __PJMEDIA_FRAME_H__
+
+/**
+ * @file pjmedia/frame.h Media frame
+ * @brief Frame
+ */
+#include <pjmedia/types.h>
+#include <pj/string.h>
+
+/**
+ * @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; i<frm->subframe_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<count; ++i) samples[i] = 0;
+#else
+ unsigned i;
+ count >>= 1;
+ for (i=0; i<count; ++i) ((pj_int32_t*)samples)[i] = (pj_int32_t)0;
+#endif
+}
+
+
+/**
+ * This is a general purpose function to copy samples from/to buffers with
+ * equal size. 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.
+ */
+PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src,
+ unsigned count)
+{
+#if 1
+ pj_memcpy(dst, src, (count<<1));
+#elif 0
+ unsigned i;
+ for (i=0; i<count; ++i) dst[i] = src[i];
+#else
+ unsigned i;
+ count >>= 1;
+ for (i=0; i<count; ++i)
+ ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i];
+#endif
+}
+
+
+/**
+ * This is a general purpose function to copy samples from/to buffers with
+ * equal size. 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.
+ */
+PJ_INLINE(void) pjmedia_move_samples(pj_int16_t *dst, const pj_int16_t *src,
+ unsigned count)
+{
+#if 1
+ pj_memmove(dst, src, (count<<1));
+#elif 0
+ unsigned i;
+ for (i=0; i<count; ++i) dst[i] = src[i];
+#else
+ unsigned i;
+ count >>= 1;
+ for (i=0; i<count; ++i)
+ ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i];
+#endif
+}
+
+PJ_END_DECL
+
+/**
+ * @}
+ */
+
+#endif /* __PJMEDIA_FRAME_H__ */
diff --git a/pjmedia/include/pjmedia/jbuf.h b/pjmedia/include/pjmedia/jbuf.h
index 18576ef9..83ee852b 100644
--- a/pjmedia/include/pjmedia/jbuf.h
+++ b/pjmedia/include/pjmedia/jbuf.h
@@ -68,7 +68,7 @@ typedef enum pjmedia_jb_frame_type pjmedia_jb_frame_type;
/**
* This structure describes jitter buffer state.
*/
-struct pjmedia_jb_state
+typedef struct pjmedia_jb_state
{
/* Setting */
unsigned frame_size; /**< Individual frame size, in bytes. */
@@ -89,13 +89,7 @@ struct pjmedia_jb_state
unsigned lost; /**< Number of lost frames. */
unsigned discard; /**< Number of discarded frames. */
unsigned empty; /**< Number of empty on GET events. */
-};
-
-
-/**
- * @see pjmedia_jb_state
- */
-typedef struct pjmedia_jb_state pjmedia_jb_state;
+} pjmedia_jb_state;
/**
@@ -180,6 +174,19 @@ PJ_DECL(pj_status_t) pjmedia_jbuf_set_adaptive( pjmedia_jbuf *jb,
/**
+ * Enable/disable the jitter buffer drift detection and handling mechanism.
+ * The default behavior is enabled.
+ *
+ * @param jb The jitter buffer
+ * @param enable Set to PJ_TRUE to enable or PJ_FALSE to disable.
+ *
+ * @return PJ_SUCCESS on success.
+ */
+PJ_DECL(pj_status_t) pjmedia_jbuf_enable_discard(pjmedia_jbuf *jb,
+ pj_bool_t enable);
+
+
+/**
* Destroy jitter buffer instance.
*
* @param jb The jitter buffer.
@@ -244,6 +251,32 @@ PJ_DECL(void) pjmedia_jbuf_put_frame2( pjmedia_jbuf *jb,
pj_bool_t *discarded);
/**
+ * Put a frame to the jitter buffer. If the frame can be accepted (based
+ * on the sequence number), the jitter buffer will copy the frame and put
+ * it in the appropriate position in the buffer.
+ *
+ * Application MUST manage it's own synchronization when multiple threads
+ * are accessing the jitter buffer at the same time.
+ *
+ * @param jb The jitter buffer.
+ * @param frame Pointer to frame buffer to be stored in the jitter
+ * buffer.
+ * @param size The frame size.
+ * @param bit_info Bit precise info of the frame, e.g: a frame may not
+ * exactly start and end at the octet boundary, so this
+ * field may be used for specifying start & end bit offset.
+ * @param frame_seq The frame sequence number.
+ * @param frame_ts The frame timestamp.
+ * @param discarded Flag whether the frame is discarded by jitter buffer.
+ */
+PJ_DECL(void) pjmedia_jbuf_put_frame3( pjmedia_jbuf *jb,
+ const void *frame,
+ pj_size_t size,
+ pj_uint32_t bit_info,
+ int frame_seq,
+ pj_uint32_t frame_ts,
+ pj_bool_t *discarded);
+/**
* Get a frame from the jitter buffer. The jitter buffer will return the
* oldest frame from it's buffer, when it is available.
*
@@ -294,6 +327,70 @@ PJ_DECL(void) pjmedia_jbuf_get_frame2(pjmedia_jbuf *jb,
/**
+ * Get a frame from the jitter buffer. The jitter buffer will return the
+ * oldest frame from it's buffer, when it is available.
+ *
+ * @param jb The jitter buffer.
+ * @param frame Buffer to receive the payload from the jitter buffer.
+ * @see pjmedia_jbuf_get_frame().
+ * @param size Pointer to receive frame size.
+ * @param p_frm_type Pointer to receive frame type.
+ * @see pjmedia_jbuf_get_frame().
+ * @param bit_info Bit precise info of the frame, e.g: a frame may not
+ * exactly start and end at the octet boundary, so this
+ * field may be used for specifying start & end bit offset.
+ * @param ts Frame timestamp.
+ * @param seq Frame sequence number.
+ */
+PJ_DECL(void) pjmedia_jbuf_get_frame3(pjmedia_jbuf *jb,
+ void *frame,
+ pj_size_t *size,
+ char *p_frm_type,
+ pj_uint32_t *bit_info,
+ pj_uint32_t *ts,
+ int *seq);
+
+
+/**
+ * Peek a frame from the jitter buffer. The jitter buffer state will not be
+ * modified.
+ *
+ * @param jb The jitter buffer.
+ * @param offset Offset from the oldest frame to be peeked.
+ * @param frame Buffer to receive the payload from the jitter buffer.
+ * @see pjmedia_jbuf_get_frame().
+ * @param size Pointer to receive frame size.
+ * @param p_frm_type Pointer to receive frame type.
+ * @see pjmedia_jbuf_get_frame().
+ * @param bit_info Bit precise info of the frame, e.g: a frame may not
+ * exactly start and end at the octet boundary, so this
+ * field may be used for specifying start & end bit offset.
+ * @param ts Frame timestamp.
+ * @param seq Frame sequence number.
+ */
+PJ_DECL(void) pjmedia_jbuf_peek_frame(pjmedia_jbuf *jb,
+ unsigned offset,
+ const void **frame,
+ pj_size_t *size,
+ char *p_frm_type,
+ pj_uint32_t *bit_info,
+ pj_uint32_t *ts,
+ int *seq);
+
+
+/**
+ * Remove frames from the jitter buffer.
+ *
+ * @param jb The jitter buffer.
+ * @param frame_cnt Number of frames to be removed.
+ *
+ * @return The number of frame successfully removed.
+ */
+PJ_DECL(unsigned) pjmedia_jbuf_remove_frame(pjmedia_jbuf *jb,
+ unsigned frame_cnt);
+
+
+/**
* Get jitter buffer current state/settings.
*
* @param jb The jitter buffer.
diff --git a/pjmedia/include/pjmedia/port.h b/pjmedia/include/pjmedia/port.h
index 5c45913c..b6493413 100644
--- a/pjmedia/include/pjmedia/port.h
+++ b/pjmedia/include/pjmedia/port.h
@@ -24,7 +24,11 @@
* @file port.h
* @brief Port interface declaration
*/
-#include <pjmedia/types.h>
+#include <pjmedia/clock.h>
+#include <pjmedia/event.h>
+#include <pjmedia/format.h>
+#include <pjmedia/frame.h>
+#include <pjmedia/signatures.h>
#include <pj/assert.h>
#include <pj/os.h>
@@ -184,6 +188,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.
*/
typedef enum pjmedia_port_op
@@ -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.
@@ -250,11 +374,18 @@ typedef struct pjmedia_port
} 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 <pjmedia/types.h>
-
+#include <pj/sock.h>
/**
* @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 <pjmedia/types.h>
+
+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 <pjmedia-audiodev/audiodev.h>
+#include <pjmedia/clock.h>
#include <pjmedia/port.h>
PJ_BEGIN_DECL
@@ -269,6 +270,19 @@ PJ_DECL(pj_status_t) pjmedia_snd_port_get_ec_tail(pjmedia_snd_port *snd_port,
/**
+ * 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
* the port's put_frame() function. If the sound device has a sound player
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 <pjmedia/port.h>
#include <pjmedia/rtcp.h>
#include <pjmedia/transport.h>
+#include <pjmedia/vid_codec.h>
#include <pj/sock.h>
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);
/**
@@ -231,6 +250,17 @@ 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 <pjmedia/codec.h>
+#include <pjmedia/sdp.h>
+
+
+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 <pjmedia/types.h>
#include <pjmedia/errno.h>
+#include <pj/string.h>
/**
* @defgroup PJMEDIA_TRANSPORT Media Transport
@@ -257,6 +258,35 @@ typedef enum 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.
*/
struct pjmedia_transport_op
@@ -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 <pjmedia/config.h>
-#include <pj/sock.h> /* pjmedia_sock_info */
-#include <pj/string.h> /* pj_memcpy(), pj_memset() */
+#include <pj/sock.h>
+#include <pj/types.h>
+
/**
* @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<count; ++i) samples[i] = 0;
-#else
- unsigned i;
- count >>= 1;
- for (i=0; i<count; ++i) ((pj_int32_t*)samples)[i] = (pj_int32_t)0;
-#endif
-}
-
+ int x; /**< X position of the coordinate */
+ int y; /**< Y position of the coordinate */
+} pjmedia_coord;
/**
- * This is a general purpose function to copy samples from/to buffers with
- * equal size. 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.
+ * This structure represents rectangle size.
*/
-PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src,
- unsigned count)
+typedef struct pjmedia_rect_size
{
-#if 1
- pj_memcpy(dst, src, (count<<1));
-#elif 0
- unsigned i;
- for (i=0; i<count; ++i) dst[i] = src[i];
-#else
- unsigned i;
- count >>= 1;
- for (i=0; i<count; ++i)
- ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i];
-#endif
-}
-
+ unsigned w; /**< The width. */
+ unsigned h; /**< The height. */
+} pjmedia_rect_size;
/**
- * This is a general purpose function to copy samples from/to buffers with
- * equal size. 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.
- */
-PJ_INLINE(void) pjmedia_move_samples(pj_int16_t *dst, const pj_int16_t *src,
- unsigned count)
-{
-#if 1
- pj_memmove(dst, src, (count<<1));
-#elif 0
- unsigned i;
- for (i=0; i<count; ++i) dst[i] = src[i];
-#else
- unsigned i;
- count >>= 1;
- for (i=0; i<count; ++i)
- ((pj_int32_t*)dst)[i] = ((pj_int32_t*)src)[i];
-#endif
-}
-
-/**
- * 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;
-
-
-/**
- * This structure describes a media frame.
+ * This structure describes a rectangle.
*/
-typedef struct pjmedia_frame
+typedef struct pjmedia_rect
{
- 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()
+ pjmedia_coord coord; /**< The position. */
+ pjmedia_rect_size size; /**< The size. */
+} pjmedia_rect;
/**
- * This structure represents the individual subframes in the
- * pjmedia_frame_ext structure.
+ * Macro for packing format from a four character code, similar to FOURCC.
*/
-#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()
+#define PJMEDIA_FOURCC(C1, C2, C3, C4) ( C4<<24 | C3<<16 | C2<<8 | C1 )
/**
- * Append one subframe to #pjmedia_frame_ext.
- *
- * @param frm The #pjmedia_frame_ext.
- * @param src Subframe data.
- * @param bitlen Lenght 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.
+ * 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; i<frm->subframe_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 <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJMEDIA_VID_CODEC_H__
+#define __PJMEDIA_VID_CODEC_H__
+
+
+/**
+ * @file vid_codec.h
+ * @brief Video codec framework.
+ */
+
+#include <pjmedia/codec.h>
+#include <pjmedia/event.h>
+#include <pjmedia/format.h>
+#include <pjmedia/types.h>
+#include <pj/list.h>
+#include <pj/pool.h>
+
+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 <benny@prijono.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef __PJMEDIA_VID_CODEC_UTIL_H__
+#define __PJMEDIA_VID_CODEC_UTIL_H__
+
+
+/**
+ * @file vid_codec_util.h
+ * @brief Video codec utilities.
+ */
+
+#include <pjmedia/vid_codec.h>
+#include <pjmedia/sdp_neg.h>
+
+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 <pjmedia-videodev/videodev.h>
+#include <pjmedia/port.h>
+
+/**
+ * @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 <pjmedia/endpoint.h>
+#include <pjmedia/jbuf.h>
+#include <pjmedia/port.h>
+#include <pjmedia/rtcp.h>
+#include <pjmedia/transport.h>
+#include <pjmedia/vid_codec.h>
+#include <pj/sock.h>
+
+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 <pjmedia/port.h>
+
+/**
+ * @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__ */