summaryrefslogtreecommitdiff
path: root/pjmedia/include/pjmedia/port.h
diff options
context:
space:
mode:
Diffstat (limited to 'pjmedia/include/pjmedia/port.h')
-rw-r--r--pjmedia/include/pjmedia/port.h258
1 files changed, 209 insertions, 49 deletions
diff --git a/pjmedia/include/pjmedia/port.h b/pjmedia/include/pjmedia/port.h
index fbc58552..cd0dbe9a 100644
--- a/pjmedia/include/pjmedia/port.h
+++ b/pjmedia/include/pjmedia/port.h
@@ -27,6 +27,206 @@
#include <pj/os.h>
+/**
+ @defgroup PJMEDIA_PORT_CONCEPT Media Ports
+ @ingroup PJMEDIA
+ @brief Extensible framework for media terminations
+
+ @section media_port_intro Concepts
+
+ @subsection The Media Port
+ A media port (represented with pjmedia_port "class") provides a generic
+ and extensible framework for implementing media terminations. A media
+ port interface basically has the following properties:
+ - media port information (pjmedia_port_info) to describe the
+ media port properties (sampling rate, number of channels, etc.),
+ - pointer to function to acquire frames from the port (<tt>get_frame()
+ </tt> interface), which will be called by #pjmedia_port_get_frame()
+ public API, and
+ - pointer to function to store frames to the port (<tt>put_frame()</tt>
+ interface) which will be called by #pjmedia_port_put_frame() public
+ API.
+
+ Media ports are passive "objects". Applications (or other PJMEDIA
+ components) must actively calls #pjmedia_port_get_frame() or
+ #pjmedia_port_put_frame() from/to the media port in order to retrieve/
+ store media frames.
+
+ Some media ports (such as @ref PJMEDIA_CONF and @ref PJMEDIA_RESAMPLE_PORT)
+ may be interconnected with each other, while some
+ others represent the ultimate source/sink termination for the media.
+ The #pjmedia_port_connect() and #pjmedia_port_disconnect() are used to
+ connect and disconnect media ports respectively. But even when ports
+ are connected with each other ports, they still remain passive.
+
+
+ @subsection port_clock_ex1 Example: Manual Resampling
+
+ For example, suppose application wants to convert the sampling rate
+ of one WAV file to another. In this case, application would create and
+ arrange media ports connection as follows:
+
+ \image html sample-manual-resampling.jpg
+
+ Application would setup the media ports using the following pseudo-
+ code:
+
+ \code
+
+ pjmedia_port *player, *resample, *writer;
+ pj_status_t status;
+
+ // Create the file player port.
+ status = pjmedia_wav_player_port_create(pool,
+ "Input.WAV", // file name
+ 20, // ptime.
+ PJMEDIA_FILE_NO_LOOP, // flags
+ 0, // buffer size
+ NULL, // user data.
+ &player );
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
+
+ // Create the resample port with specifying the target sampling rate,
+ // and with the file port as the source. This will effectively
+ // connect the resample port with the player port.
+ status = pjmedia_resample_port_create( pool, player, 8000,
+ 0, &resample);
+ PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
+
+ // Create the file writer, specifying the resample port's configuration
+ // as the WAV parameters.
+ status pjmedia_wav_writer_port_create(pool,
+ "Output.WAV", // file name.
+ resample->info.clock_rate,
+ resample->info.channel_count,
+ resample->info.samples_per_frame,
+ resample->info.bits_per_sample,
+ 0, // flags
+ 0, // buffer size
+ NULL, // user data.
+ &writer);
+
+ \endcode
+
+
+ After the ports have been set up, application can perform the conversion
+ process by running this loop:
+
+ \code
+
+ pj_int16_t samplebuf[MAX_FRAME];
+
+ while (1) {
+ pjmedia_frame frame;
+ pj_status_t status;
+
+ frame.buf = samplebuf;
+ frame.size = sizeof(samplebuf);
+
+ // Get the frame from resample port.
+ status = pjmedia_port_get_frame(resample, &frame);
+ if (status != PJ_SUCCESS || frame.type == PJMEDIA_FRAME_TYPE_NONE) {
+ // End-of-file, end the conversion.
+ break;
+ }
+
+ // Put the frame to write port.
+ status = pjmedia_port_put_frame(writer, &frame);
+ if (status != PJ_SUCCESS) {
+ // Error in writing the file.
+ break;
+ }
+ }
+
+ \endcode
+
+ For the sake of completeness, after the resampling process is done,
+ application would need to destroy the ports:
+
+ \code
+ // Note: by default, destroying resample port will destroy the
+ // the downstream port too.
+ pjmedia_port_destroy(resample);
+ pjmedia_port_destroy(writer);
+ \endcode
+
+
+ The above steps are okay for our simple purpose of changing file's sampling
+ rate. But for other purposes, the process of reading and writing frames
+ need to be done in timely manner (for example, sending RTP packets to
+ remote stream). And more over, as the application's scope goes bigger,
+ the same pattern of manually reading/writing frames comes up more and more often,
+ thus perhaps it would be better if PJMEDIA provides mechanism to
+ automate this process.
+
+ And indeed PJMEDIA does provide such mechanism, which is described in
+ @ref PJMEDIA_PORT_CLOCK section.
+
+
+ @subsection media_port_autom Automating Media Flow
+
+ PJMEDIA provides few mechanisms to make media flows automatically
+ among media ports. This concept is described in @ref PJMEDIA_PORT_CLOCK
+ section.
+
+ */
+
+
+/**
+ * @defgroup PJMEDIA_PORT_INTERFACE Media Port Interface
+ * @ingroup PJMEDIA_PORT_CONCEPT
+ * @brief Declares the media port interface.
+ */
+
+/**
+ * @defgroup PJMEDIA_PORT Ports
+ * @ingroup PJMEDIA_PORT_CONCEPT
+ * @brief Contains various types of media ports/terminations.
+ * @{
+ * This page lists all types of media ports currently implemented
+ * in PJMEDIA. The media port concept is explained in @ref PJMEDIA_PORT_CONCEPT.
+ * @}
+ */
+
+/**
+ @defgroup PJMEDIA_PORT_CLOCK Clock/Timing
+ @ingroup PJMEDIA_PORT_CONCEPT
+ @brief Various types of classes that provide timing.
+ @{
+
+ The media clock/timing extends the media port concept that is explained
+ in @ref PJMEDIA_PORT_CONCEPT. When clock is present in the ports
+ interconnection, media will flow automatically (and with correct timing too!)
+ from one media port to another.
+
+ There are few objects in PJMEDIA that are able to provide clock/timing
+ to media ports interconnection:
+
+ - @ref PJMED_SND_PORT\n
+ The sound device makes a good candidate as the clock source, and
+ PJMEDIA @ref PJMED_SND is designed so that it is able to invoke
+ operations according to timing driven by the sound hardware clock
+ (this may sound complicated, but actually it just means that
+ the sound device abstraction provides callbacks to be called when
+ it has/wants media frames).\n
+ See @ref PJMED_SND_PORT for more details.
+
+ - @ref PJMEDIA_MASTER_PORT\n
+ The master port uses @ref PJMEDIA_CLOCK as the clock source. By using
+ @ref PJMEDIA_MASTER_PORT, it is possible to interconnect passive
+ media ports and let the frames flow automatically in timely manner.\n
+ Please see @ref PJMEDIA_MASTER_PORT for more details.
+
+ @}
+ */
+
+/**
+ * @addtogroup PJMEDIA_PORT_INTERFACE
+ * @{
+ * This page contains the media port interface declarations. The media port
+ * concept is explained in @ref PJMEDIA_PORT_CONCEPT.
+ */
+
PJ_BEGIN_DECL
@@ -68,7 +268,7 @@ typedef enum pjmedia_port_op pjmedia_port_op;
/**
* Port info.
*/
-struct pjmedia_port_info
+typedef struct pjmedia_port_info
{
pj_str_t name; /**< Port name. */
pj_uint32_t signature; /**< Port signature. */
@@ -82,30 +282,19 @@ struct pjmedia_port_info
unsigned bits_per_sample; /**< Bits/sample */
unsigned samples_per_frame; /**< No of samples per frame. */
unsigned bytes_per_frame; /**< No of samples per frame. */
-};
-
-/**
- * @see pjmedia_port_info
- */
-typedef struct pjmedia_port_info pjmedia_port_info;
+} pjmedia_port_info;
/**
* Types of media frame.
*/
-enum pjmedia_frame_type
+typedef enum pjmedia_frame_type
{
PJMEDIA_FRAME_TYPE_NONE, /**< No frame. */
PJMEDIA_FRAME_TYPE_CNG, /**< Silence audio frame. */
PJMEDIA_FRAME_TYPE_AUDIO, /**< Normal audio frame. */
-};
-
-
-/**
- * @see pjmedia_frame_type
- */
-typedef enum pjmedia_frame_type pjmedia_frame_type;
+} pjmedia_frame_type;
/**
@@ -142,25 +331,8 @@ typedef struct pjmedia_port pjmedia_port;
*/
struct pjmedia_port
{
- pjmedia_port_info info;
- pjmedia_graph *graph;
- pjmedia_port *upstream_port;
- pjmedia_port *downstream_port;
- void *user_data;
-
- /**
- * Called when this port is connected to an upstream port.
- */
- pj_status_t (*on_upstream_connect)(pj_pool_t *pool,
- pjmedia_port *this_port,
- pjmedia_port *upstream);
-
- /**
- * Called when this port is connected to a downstream port.
- */
- pj_status_t (*on_downstream_connect)(pj_pool_t *pool,
- pjmedia_port *this_port,
- pjmedia_port *upstream);
+ pjmedia_port_info info; /**< Port information. */
+ void *user_data; /**< User data. */
/**
* Sink interface.
@@ -183,21 +355,6 @@ struct pjmedia_port
};
-
-/**
- * Connect two ports.
- */
-PJ_DECL(pj_status_t) pjmedia_port_connect( pj_pool_t *pool,
- pjmedia_port *upstream_port,
- pjmedia_port *downstream_port);
-
-/**
- * Disconnect ports.
- */
-PJ_DECL(pj_status_t) pjmedia_port_disconnect( pjmedia_port *upstream_port,
- pjmedia_port *downstream_port);
-
-
/**
* Get a frame from the port (and subsequent downstream ports).
*/
@@ -220,6 +377,9 @@ PJ_DECL(pj_status_t) pjmedia_port_destroy( pjmedia_port *port );
PJ_END_DECL
+/**
+ * @}
+ */
#endif /* __PJMEDIA_PORT_H__ */