Updated doxygen documentation to all headers in PJMEDIA
git-svn-id: https://svn.pjsip.org/repos/pjproject/trunk@518 74dad513-b988-da41-8d7b-12977e46ad98
This commit is contained in:
parent
5520dfda07
commit
37235afb40
|
@ -92,12 +92,13 @@ SPEEX_OBJS := speex_codec.o \
|
|||
speex/bits.o speex/cb_search.o speex/exc_10_16_table.o \
|
||||
speex/exc_10_32_table.o speex/exc_20_32_table.o \
|
||||
speex/exc_5_256_table.o speex/exc_5_64_table.o \
|
||||
speex/exc_8_128_table.o speex/filters.o \
|
||||
speex/exc_8_128_table.o speex/fftwrap.c speex/filters.o \
|
||||
speex/gain_table.o speex/gain_table_lbr.o \
|
||||
speex/hexc_10_32_table.o speex/hexc_table.o \
|
||||
speex/high_lsp_tables.o speex/lpc_spx.o \
|
||||
speex/high_lsp_tables.o speex/jitter.c \
|
||||
speex/kiss_fft.c speex/kiss_fftr.c speex/lpc_spx.o \
|
||||
speex/lsp.o speex/lsp_tables_nb.o speex/ltp.o \
|
||||
speex/math_approx.o speex/misc.o speex/modes.o \
|
||||
speex/math_approx.o speex/misc.o speex/mdf.c speex/modes.o \
|
||||
speex/nb_celp.o speex/preprocess_spx.o \
|
||||
speex/quant_lsp.o speex/sb_celp.o speex/smallft.o \
|
||||
speex/speex.o speex/speex_callbacks.o speex/speex_header.o \
|
||||
|
|
|
@ -311,6 +311,10 @@ SOURCE=..\include\pjmedia\stream.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\include\pjmedia\transport.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=..\include\pjmedia\transport_udp.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -226,6 +226,10 @@ SOURCE="..\src\pjmedia-codec\gsm\unproto.h"
|
|||
# PROP Default_Filter ""
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\_kiss_fft_guts.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\arch.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -250,6 +254,10 @@ SOURCE="..\src\pjmedia-codec\speex\config.h"
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\fftwrap.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\filters.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -286,6 +294,14 @@ SOURCE="..\src\pjmedia-codec\speex\fixed_generic.h"
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\kiss_fft.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\kiss_fftr.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\lpc.h"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -454,6 +470,10 @@ SOURCE="..\src\pjmedia-codec\speex\exc_8_128_table.c"
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\fftwrap.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\filters.c"
|
||||
# ADD CPP /W4
|
||||
# End Source File
|
||||
|
@ -484,6 +504,18 @@ SOURCE="..\src\pjmedia-codec\speex\high_lsp_tables.c"
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\jitter.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\kiss_fft.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\kiss_fftr.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\lpc_spx.c"
|
||||
# ADD CPP /W4
|
||||
# End Source File
|
||||
|
@ -509,6 +541,10 @@ SOURCE="..\src\pjmedia-codec\speex\math_approx.c"
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\mdf.c"
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE="..\src\pjmedia-codec\speex\misc.c"
|
||||
# ADD CPP /W4
|
||||
# End Source File
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
|
||||
# by quotes) that should identify the project.
|
||||
|
||||
PROJECT_NAME = PJMEDIA
|
||||
PROJECT_NAME = "PJMEDIA and PJMEDIA-CODEC"
|
||||
|
||||
# The PROJECT_NUMBER tag can be used to enter a project or revision number.
|
||||
# This could be handy for archiving the generated documentation or
|
||||
|
@ -107,7 +107,7 @@ BRIEF_MEMBER_DESC = YES
|
|||
# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
|
||||
# brief descriptions will be completely suppressed.
|
||||
|
||||
REPEAT_BRIEF = YES
|
||||
REPEAT_BRIEF = NO
|
||||
|
||||
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
|
||||
# Doxygen will generate a detailed section even if there is only a brief
|
||||
|
@ -133,7 +133,7 @@ FULL_PATH_NAMES = NO
|
|||
# only done if one of the specified strings matches the left-hand part of
|
||||
# the path. It is allowed to use relative paths in the argument list.
|
||||
|
||||
STRIP_FROM_PATH = "c:\project\pjproject"
|
||||
STRIP_FROM_PATH = "/c/project/pjproject/pjmedia"
|
||||
|
||||
# The INTERNAL_DOCS tag determines if documentation
|
||||
# that is typed after a \internal command is included. If the tag is set
|
||||
|
@ -154,7 +154,7 @@ CASE_SENSE_NAMES = YES
|
|||
# (but less readable) file names. This can be useful is your file systems
|
||||
# doesn't support long names like on DOS, Mac, or CD-ROM.
|
||||
|
||||
SHORT_NAMES = YES
|
||||
SHORT_NAMES = NO
|
||||
|
||||
# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
|
||||
# will show members with their full class and namespace scopes in the
|
||||
|
@ -166,7 +166,7 @@ HIDE_SCOPE_NAMES = NO
|
|||
# will generate a verbatim copy of the header file for each class for
|
||||
# which an include is specified. Set to NO to disable this.
|
||||
|
||||
VERBATIM_HEADERS = YES
|
||||
VERBATIM_HEADERS = NO
|
||||
|
||||
# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
|
||||
# will put list of the files that are included by a file in the documentation
|
||||
|
@ -345,7 +345,7 @@ WARN_LOGFILE =
|
|||
# directories like "/usr/src/myproject". Separate the files or directories
|
||||
# with spaces.
|
||||
|
||||
INPUT = include/pjmedia
|
||||
INPUT = include
|
||||
|
||||
# If the value of the INPUT tag contains directories, you can use the
|
||||
# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
|
||||
|
@ -403,7 +403,7 @@ EXAMPLE_RECURSIVE = NO
|
|||
# directories that contain image that are included in the documentation (see
|
||||
# the \image command).
|
||||
|
||||
IMAGE_PATH =
|
||||
IMAGE_PATH = docs
|
||||
|
||||
# The INPUT_FILTER tag can be used to specify a program that doxygen should
|
||||
# invoke to filter for each input file. Doxygen will invoke the filter program
|
||||
|
@ -494,7 +494,7 @@ HTML_OUTPUT = html
|
|||
# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
|
||||
# doxygen will generate files with .html extension.
|
||||
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_FILE_EXTENSION = .htm
|
||||
|
||||
# The HTML_HEADER tag can be used to specify a personal HTML header for
|
||||
# each generated HTML page. If it is left blank doxygen will generate a
|
||||
|
@ -568,7 +568,7 @@ DISABLE_INDEX = NO
|
|||
# This tag can be used to set the number of enum values (range [1..20])
|
||||
# that doxygen will group on one line in the generated HTML documentation.
|
||||
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
ENUM_VALUES_PER_LINE = 1
|
||||
|
||||
# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
|
||||
# generated containing a tree-like index structure (just like the one that
|
||||
|
@ -842,7 +842,8 @@ INCLUDE_FILE_PATTERNS =
|
|||
# omitted =1 is assumed.
|
||||
|
||||
PREDEFINED = PJ_DECL(x)=x PJ_DEF(x)=x PJ_IDECL(x)=x \
|
||||
PJ_IDEF(x)=x PJ_INLINE(x)=x
|
||||
PJ_IDEF(x)=x PJ_INLINE(x)=x \
|
||||
PJ_BEGIN_DECL= PJ_END_DECL=
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<!--#include virtual="/footer.html" -->
|
||||
</BODY>
|
||||
</HTML>
|
||||
|
|
|
@ -1,32 +1,7 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
|
||||
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
|
||||
<title>PJMEDIA Documentation</title>
|
||||
<link href="doxygen.css" rel="stylesheet" type="text/css">
|
||||
<title>PJMEDIA - Open Source media stack with RTP, RTCP, SDP, conference bridge, PLC, VAD, etc.</title>
|
||||
<link href="/style/style.css" rel="stylesheet" type="text/css">
|
||||
</head><body>
|
||||
|
||||
<TABLE id="MainTable" cellSpacing="0" cellPadding="0" width="100%" border="0">
|
||||
<!-- First Row, PJPROJECT logo. -->
|
||||
<TR>
|
||||
<TD>
|
||||
<TABLE id="LogoTable" cellSpacing="0" cellPadding="0" width="100%" border="0">
|
||||
<TR>
|
||||
<TD><a href="/" target="_top"><IMG src="/images/pjlogo.jpg" border="0"></a></TD>
|
||||
<TD> </TD>
|
||||
<TD> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
<!-- Second Row, a HR. -->
|
||||
<TR>
|
||||
<td colspan="3"><hr noshade size="1">
|
||||
</td>
|
||||
</TR>
|
||||
<!-- Third row, main contents. -->
|
||||
<TR>
|
||||
<TD>
|
||||
|
||||
<!-- Main doxygen content -->
|
||||
<TABLE border="0">
|
||||
<TR><TD width="800" align="left">
|
||||
<!--#include virtual="/header.html" -->
|
||||
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -19,8 +19,22 @@
|
|||
#ifndef __PJMEDIA_CODEC_GSM_H__
|
||||
#define __PJMEDIA_CODEC_GSM_H__
|
||||
|
||||
/**
|
||||
* @file pjmedia-codec/gsm.h
|
||||
* @brief GSM 06.10 codec.
|
||||
*/
|
||||
|
||||
#include <pjmedia-codec/types.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_GSM GSM 06.10
|
||||
* @ingroup PJMEDIA_CODEC
|
||||
* @brief Implementation of GSM FR based on GSM 06.10 library
|
||||
* @{
|
||||
* This section describes functions to register and register GSM codec
|
||||
* factory to the codec manager. After the codec factory has been registered,
|
||||
* application can use @ref PJMEDIA_CODEC API to manipulate the codec.
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
@ -48,5 +62,9 @@ PJ_DECL(pj_status_t) pjmedia_codec_gsm_deinit(void);
|
|||
PJ_END_DECL
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __PJMEDIA_CODEC_GSM_H__ */
|
||||
|
||||
|
|
|
@ -22,6 +22,20 @@
|
|||
#include <pjmedia-codec/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_L16 L16 Family
|
||||
* @ingroup PJMEDIA_CODEC
|
||||
* @brief 16bit linear codecs (useful for debugging)
|
||||
* @{
|
||||
* This section describes functions to register and register L16 codec
|
||||
* factory to the codec manager. After the codec factory has been registered,
|
||||
* application can use @ref PJMEDIA_CODEC API to manipulate the codec.
|
||||
*
|
||||
* Note that the L16 codec factory registers several (about fourteen!)
|
||||
* L16 codec types to codec manager (different combinations of clock
|
||||
* rate and number of channels).
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
|
|
|
@ -19,8 +19,27 @@
|
|||
#ifndef __PJMEDIA_CODEC_SPEEX_H__
|
||||
#define __PJMEDIA_CODEC_SPEEX_H__
|
||||
|
||||
/**
|
||||
* @file speex.h
|
||||
* @brief Speex codec header.
|
||||
*/
|
||||
|
||||
#include <pjmedia-codec/types.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_SPEEX Speex
|
||||
* @ingroup PJMEDIA_CODEC
|
||||
* @brief Implementation of Speex codecs (narrow/wide/ultrawide-band).
|
||||
* @{
|
||||
* This section describes functions to register and register speex codec
|
||||
* factory to the codec manager. After the codec factory has been registered,
|
||||
* application can use @ref PJMEDIA_CODEC API to manipulate the codec.
|
||||
*
|
||||
* By default, the speex codec factory registers three Speex codecs:
|
||||
* "speex/8000" narrowband codec, "speex/16000" wideband codec, and
|
||||
* "speex/32000" ultra-wideband codec. This behavior can be changed by
|
||||
* specifying #pjmedia_speex_options flags during initialization.
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
@ -59,11 +78,6 @@ PJ_DECL(pj_status_t) pjmedia_codec_speex_init( pjmedia_endpt *endpt,
|
|||
* pjmedia endpoint.
|
||||
*
|
||||
* @param endpt The pjmedia endpoint.
|
||||
* @param options Bitmask of pjmedia_speex_options (default=0).
|
||||
* @param quality Specify encoding quality, or use -1 for default
|
||||
* (default=8).
|
||||
* @param complexity Specify encoding complexity , or use -1 for default
|
||||
* (default=8).
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
|
@ -82,6 +96,9 @@ PJ_DECL(pj_status_t) pjmedia_codec_speex_deinit(void);
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __PJMEDIA_CODEC_SPEEX_H__ */
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include <pjmedia/sdp_neg.h>
|
||||
#include <pjmedia/silencedet.h>
|
||||
#include <pjmedia/session.h>
|
||||
#include <pjmedia/transport.h>
|
||||
#include <pjmedia/transport_udp.h>
|
||||
#include <pjmedia/sound.h>
|
||||
#include <pjmedia/sound_port.h>
|
||||
|
|
|
@ -26,6 +26,23 @@
|
|||
#include <pjmedia/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @addtogroup PJMEDIA_CLOCK Clock Generator
|
||||
* @ingroup PJMEDIA_PORT_CLOCK
|
||||
* @brief Interface for generating clock.
|
||||
* @{
|
||||
*
|
||||
* The clock generator provides the application with media timing,
|
||||
* and it is used by the @ref PJMEDIA_MASTER_PORT for its sound clock.
|
||||
*
|
||||
* The clock generator may be configured to run <b>asynchronously</b>
|
||||
* (the default behavior) or <b>synchronously</b>. When it is run
|
||||
* asynchronously, it will call the application's callback every time
|
||||
* the clock <b>tick</b> expires. When it is run synchronously,
|
||||
* application must continuously polls the clock generator to synchronize
|
||||
* the timing.
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
|
@ -35,11 +52,20 @@ PJ_BEGIN_DECL
|
|||
typedef struct pjmedia_clock pjmedia_clock;
|
||||
|
||||
|
||||
/**
|
||||
* Options when creating the clock.
|
||||
*/
|
||||
enum pjmedia_clock_options
|
||||
{
|
||||
/**
|
||||
* Prevents the clock from running asynchronously. In this case,
|
||||
* application must poll the clock continuously by calling
|
||||
* #pjmedia_clock_wait() in order to synchronize timing.
|
||||
*/
|
||||
PJMEDIA_CLOCK_NO_ASYNC = 1,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Type of media clock callback.
|
||||
*
|
||||
|
@ -137,6 +163,9 @@ PJ_DECL(pj_status_t) pjmedia_clock_destroy(pjmedia_clock *clock);
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_CLOCK_H__ */
|
||||
|
|
|
@ -32,24 +32,165 @@ PJ_BEGIN_DECL
|
|||
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_CODEC Codec framework.
|
||||
* @defgroup PJMEDIA_CODEC Codec Framework
|
||||
* @ingroup PJMEDIA
|
||||
* @brief Media codec framework and management
|
||||
* @{
|
||||
*
|
||||
* The codec manager is used to manage all codec capabilities in the endpoint.
|
||||
* Library implementors can extend PJMEDIA codec capabilities by creating
|
||||
* a codec factory for a new codec, and register the codec factory to
|
||||
* codec manager so that the codec can be used by the rest of application.
|
||||
* @section codec_mgmt_sec Codec Management
|
||||
* @subsection codec_fact_sec Codec Manager
|
||||
*
|
||||
* The codec manager is used to manage all codec capabilities in the endpoint.
|
||||
* When used with media endpoint (pjmedia_endpt), application can retrieve
|
||||
* the codec manager instance by calling #pjmedia_endpt_get_codec_mgr().
|
||||
*
|
||||
* @subsection reg_new_codec Registering New Codec
|
||||
*
|
||||
* New codec types can be registered to PJMEDIA (or to be precise, to the
|
||||
* codec manager) during run-time.
|
||||
* To do this, application needs to initialize an instance of
|
||||
* codec factory (#pjmedia_codec_factory) and registers this codec factory
|
||||
* by calling #pjmedia_codec_mgr_register_factory().
|
||||
*
|
||||
* For codecs implemented/supported by PJMEDIA, this process is normally
|
||||
* concealed in an easy to use function such as #pjmedia_codec_g711_init().
|
||||
*
|
||||
* @subsection codec_factory Codec Factory
|
||||
*
|
||||
* A codec factory (#pjmedia_codec_factory) is registered to codec manager,
|
||||
* and it is used to create and release codec instance.
|
||||
*
|
||||
* The most important member of the codec factory is the "virtual" function
|
||||
* table #pjmedia_codec_factory_op, where it contains, among other thing,
|
||||
* pointer to functions to allocate and deallocate codec instance.
|
||||
*
|
||||
* @subsection codec_inst Codec Instance
|
||||
*
|
||||
* Application allocates codec instance by calling #pjmedia_codec_mgr_alloc_codec().
|
||||
* One codec instance (#pjmedia_codec) can be used for simultaneous encoding
|
||||
* and decoding.
|
||||
*
|
||||
* The most important member of the codec instance is the "virtual" function
|
||||
* table #pjmedia_codec_op, where it holds pointer to functions to
|
||||
* encode/decode media frames.
|
||||
*
|
||||
* @subsection codec_ident Codec Identification
|
||||
*
|
||||
* A particular codec type in PJMEDIA can be uniquely identified by two
|
||||
* keys: by #pjmedia_codec_info, or by #pjmedia_codec_id string. A fully
|
||||
* qualified codec ID string consists of codec name, sampling rate, and
|
||||
* number of channels. However, application may use only first parts of
|
||||
* the tokens as long as it will make to codec ID unique. For example, "gsm"
|
||||
* is a fully qualified codec name, since it will always have 8000 clock
|
||||
* rate and 1 channel. Other examples of fully qualified codec ID strings
|
||||
* are "pcma", "speex/8000", "speex/16000", and "L16/16000/1". A codec
|
||||
* id "speex" (without clock rate) is not fully qualified, since it will
|
||||
* match the narrowband, wideband, and ultrawideband Speex codec.
|
||||
*
|
||||
* The two keys can be converted to one another, with
|
||||
* #pjmedia_codec_info_to_id() and #pjmedia_codec_mgr_find_codecs_by_id()
|
||||
* functions.
|
||||
*
|
||||
* Codec ID string is not case sensitive.
|
||||
*
|
||||
*
|
||||
* @section using_codec Using the Codec Framework
|
||||
* @subsection init_alloc_codec Allocating Codec
|
||||
*
|
||||
* Application needs to allocate one codec instance for encoding and decoding
|
||||
* media frames. One codec instance can be used to perform both encoding
|
||||
* and decoding.
|
||||
*
|
||||
* Application allocates codec by calling #pjmedia_codec_mgr_alloc_codec().
|
||||
* This function takes #pjmedia_codec_info argument, which is used to locate
|
||||
* the particular codec factory to be used to allocate the codec.
|
||||
*
|
||||
* Application can build #pjmedia_codec_info structure manually for
|
||||
* the specific codec, or alternatively it may get the #pjmedia_codec_info
|
||||
* from the codec ID string, by using #pjmedia_codec_mgr_find_codecs_by_id()
|
||||
* function.
|
||||
*
|
||||
* The following snippet shows an example to allocate a codec:
|
||||
*
|
||||
\code
|
||||
pj_str_t codec_id;
|
||||
pjmedia_codec_info *codec_info;
|
||||
unsigned count = 1;
|
||||
pjmedia_codec *codec;
|
||||
|
||||
codec_id = pj_str("pcma");
|
||||
|
||||
// Find codec info for the specified coded ID (i.e. "pcma").
|
||||
status = pjmedia_codec_mgr_find_codecs_by_id( codec_mgr, &codec_id,
|
||||
&count, &codec_info, NULL);
|
||||
|
||||
// Allocate the codec.
|
||||
status = pjmedia_codec_mgr_alloc_codec( codec_mgr, codec_info, &codec );
|
||||
|
||||
\endcode
|
||||
*
|
||||
*
|
||||
* @subsection opening_codec Initializing Codec
|
||||
*
|
||||
* Once codec is allocated, application needs to initialize the codec
|
||||
* by calling <b><tt>open</tt></b> member of the codec. This function
|
||||
* takes #pjmedia_codec_param as the argument, which contains the
|
||||
* settings for the codec.
|
||||
*
|
||||
* Application shoud use #pjmedia_codec_mgr_get_default_param() function
|
||||
* to initiaize #pjmedia_codec_param. The <tt>setting</tt> part of
|
||||
* #pjmedia_codec_param then can be tuned to suit the application's
|
||||
* requirements.
|
||||
*
|
||||
* The following snippet shows an example to initialize codec:
|
||||
*
|
||||
\code
|
||||
pjmedia_codec_param param;
|
||||
|
||||
// Retrieve default codec param for the specified codec.
|
||||
pjmedia_codec_mgr_get_default_param(codec_mgr, codec_info
|
||||
¶m);
|
||||
|
||||
// Application may change the "settings" part of codec param,
|
||||
// for example, to disable VAD
|
||||
param.setting.vad = 0;
|
||||
|
||||
// Open the codec using the specified settings.
|
||||
codec->op->open( codec, ¶m );
|
||||
|
||||
\endcode
|
||||
*
|
||||
*
|
||||
* @subsection enc_dec_codec Encoding and Decoding Media Frames
|
||||
*
|
||||
* Application encodes and decodes media frames by calling
|
||||
* <tt>encode</tt> and <tt>decode</tt> member of the codec's "virtual"
|
||||
* function table (#pjmedia_codec_op).
|
||||
*
|
||||
* @subsection plc_codec Concealing Lost Frames
|
||||
*
|
||||
* All codecs has Packet Lost Concealment (PLC) feature, and application
|
||||
* can activate the PLC to conceal lost frames by calling <tt>recover</tt>
|
||||
* member of the codec's "virtual" function table (#pjmedia_codec_op).
|
||||
*
|
||||
* If the codec's algorithm supports PLC, the <tt>recover</tt> function
|
||||
* will use the codec's PLC. Otherwise for codecs that don't have
|
||||
* intrinsic PLC, PJMEDIA will suply the PLC implementation from the
|
||||
* @ref PJMED_PLC implementation.
|
||||
*
|
||||
* @subsection close_codec Closing and Releasing the Codec
|
||||
*
|
||||
* The codec must be closed by calling <tt>close</tt> member of the codec's
|
||||
* operation. Then it must be released by calling
|
||||
* #pjmedia_codec_mgr_dealloc_codec().
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Standard RTP static payload types, as defined by RFC 3551.
|
||||
* The header file <pjmedia-codec/types.h> also declares dynamic payload
|
||||
* types that are supported by pjmedia-codec library.
|
||||
* type numbers that are used by PJMEDIA when advertising the capability
|
||||
* for example in SDP message.
|
||||
*/
|
||||
enum pjmedia_rtp_pt
|
||||
{
|
||||
|
@ -88,27 +229,21 @@ enum pjmedia_rtp_pt
|
|||
* Identification used to search for codec factory that supports specific
|
||||
* codec specification.
|
||||
*/
|
||||
struct pjmedia_codec_info
|
||||
typedef struct pjmedia_codec_info
|
||||
{
|
||||
pjmedia_type type; /**< Media type. */
|
||||
unsigned pt; /**< Payload type (can be dynamic). */
|
||||
pj_str_t encoding_name; /**< Encoding name. */
|
||||
unsigned clock_rate; /**< Sampling rate. */
|
||||
unsigned channel_cnt; /**< Channel count. */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec_info
|
||||
*/
|
||||
typedef struct pjmedia_codec_info pjmedia_codec_info;
|
||||
} pjmedia_codec_info;
|
||||
|
||||
|
||||
/**
|
||||
* Detailed codec attributes used both to configure a codec and to query
|
||||
* the capability of codec factories.
|
||||
*/
|
||||
struct pjmedia_codec_param
|
||||
typedef struct pjmedia_codec_param
|
||||
{
|
||||
/**
|
||||
* The "info" part of codec param describes the capability of the codec,
|
||||
|
@ -142,16 +277,12 @@ struct pjmedia_codec_param
|
|||
unsigned plc:1; /**< Packet loss concealment */
|
||||
unsigned reserved:1; /**< Reserved, must be zero. */
|
||||
} setting;
|
||||
};
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec_param
|
||||
*/
|
||||
typedef struct pjmedia_codec_param pjmedia_codec_param;
|
||||
} pjmedia_codec_param;
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec
|
||||
|
||||
/*
|
||||
* Forward declaration for pjmedia_codec.
|
||||
*/
|
||||
typedef struct pjmedia_codec pjmedia_codec;
|
||||
|
||||
|
@ -160,7 +291,7 @@ typedef struct pjmedia_codec pjmedia_codec;
|
|||
* This structure describes codec operations. Each codec MUST implement
|
||||
* all of these functions.
|
||||
*/
|
||||
struct pjmedia_codec_op
|
||||
typedef struct pjmedia_codec_op
|
||||
{
|
||||
/**
|
||||
* Initialize codec using the specified attribute.
|
||||
|
@ -258,29 +389,24 @@ struct pjmedia_codec_op
|
|||
struct pjmedia_frame *output);
|
||||
|
||||
/**
|
||||
* Instruct the codec to recover a missing frame. Not all codec has
|
||||
* this capability, so this function may be NULL.
|
||||
* 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.
|
||||
* @param output The output frame where generated signal
|
||||
* will be placed.
|
||||
*
|
||||
* @return PJ_SUCCESS on success;
|
||||
*/
|
||||
pj_status_t (*recover)(pjmedia_codec *codec,
|
||||
unsigned out_size,
|
||||
struct pjmedia_frame *output);
|
||||
};
|
||||
} pjmedia_codec_op;
|
||||
|
||||
|
||||
/**
|
||||
* Codec operation.
|
||||
*/
|
||||
typedef struct pjmedia_codec_op pjmedia_codec_op;
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec_factory
|
||||
/*
|
||||
* Forward declaration for pjmedia_codec_factory.
|
||||
*/
|
||||
typedef struct pjmedia_codec_factory pjmedia_codec_factory;
|
||||
|
||||
|
@ -309,7 +435,7 @@ struct pjmedia_codec
|
|||
* This structure describes operations that must be supported by codec
|
||||
* factories.
|
||||
*/
|
||||
struct pjmedia_codec_factory_op
|
||||
typedef struct pjmedia_codec_factory_op
|
||||
{
|
||||
/**
|
||||
* Check whether the factory can create codec with the specified
|
||||
|
@ -380,14 +506,9 @@ struct pjmedia_codec_factory_op
|
|||
pj_status_t (*dealloc_codec)(pjmedia_codec_factory *factory,
|
||||
pjmedia_codec *codec );
|
||||
|
||||
};
|
||||
} pjmedia_codec_factory_op;
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec_factory_op
|
||||
*/
|
||||
typedef struct pjmedia_codec_factory_op pjmedia_codec_factory_op;
|
||||
|
||||
|
||||
/**
|
||||
* Codec factory describes a module that is able to create codec with specific
|
||||
|
@ -418,7 +539,7 @@ struct pjmedia_codec_factory
|
|||
* Specify these values to set the codec priority, by calling
|
||||
* #pjmedia_codec_mgr_set_codec_priority().
|
||||
*/
|
||||
enum pjmedia_codec_priority
|
||||
typedef enum pjmedia_codec_priority
|
||||
{
|
||||
/**
|
||||
* This priority makes the codec the highest in the order.
|
||||
|
@ -455,16 +576,14 @@ enum pjmedia_codec_priority
|
|||
* query functions.
|
||||
*/
|
||||
PJMEDIA_CODEC_PRIO_DISABLED = 0,
|
||||
};
|
||||
|
||||
} pjmedia_codec_priority;
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec_priority
|
||||
/**
|
||||
* Codec identification (e.g. "pcmu/8000/1").
|
||||
* See @ref codec_ident for more info.
|
||||
*/
|
||||
typedef enum pjmedia_codec_priority pjmedia_codec_priority;
|
||||
|
||||
|
||||
/** Fully qualified codec name (e.g. "pcmu/8000/1") */
|
||||
typedef char pjmedia_codec_id[32];
|
||||
|
||||
|
||||
|
@ -486,7 +605,7 @@ struct pjmedia_codec_desc
|
|||
* to see this declaration, but nevertheless this declaration is needed
|
||||
* by media endpoint to instantiate the codec manager.
|
||||
*/
|
||||
struct pjmedia_codec_mgr
|
||||
typedef struct pjmedia_codec_mgr
|
||||
{
|
||||
/** List of codec factories registered to codec manager. */
|
||||
pjmedia_codec_factory factory_list;
|
||||
|
@ -496,13 +615,8 @@ struct pjmedia_codec_mgr
|
|||
|
||||
/** Array of codec descriptor. */
|
||||
struct pjmedia_codec_desc codec_desc[PJMEDIA_CODEC_MGR_MAX_CODECS];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_codec_mgr
|
||||
*/
|
||||
typedef struct pjmedia_codec_mgr pjmedia_codec_mgr;
|
||||
} pjmedia_codec_mgr;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -26,6 +26,12 @@
|
|||
*/
|
||||
#include <pjmedia/port.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_CONF Conference Bridge
|
||||
* @ingroup PJMEDIA_PORT
|
||||
* @brief The implementation of conference bridge
|
||||
* @{
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
@ -236,7 +242,7 @@ PJ_DECL(pj_status_t) pjmedia_conf_connect_port( pjmedia_conf *conf,
|
|||
* @param src_slot Source slot.
|
||||
* @param sink_slot Sink slot.
|
||||
*
|
||||
* @reutrn PJ_SUCCESS on success.
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_conf_disconnect_port( pjmedia_conf *conf,
|
||||
unsigned src_slot,
|
||||
|
@ -373,5 +379,10 @@ PJ_DECL(pj_status_t) pjmedia_conf_adjust_tx_level( pjmedia_conf *conf,
|
|||
PJ_END_DECL
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_CONF_H__ */
|
||||
|
||||
|
|
|
@ -19,13 +19,35 @@
|
|||
#ifndef __PJMEDIA_CONFIG_H__
|
||||
#define __PJMEDIA_CONFIG_H__
|
||||
|
||||
/**
|
||||
* @file pjmedia/config.h Compile time config
|
||||
* @brief Contains some compile time constants.
|
||||
*/
|
||||
#include <pj/config.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_BASE Base Types and Configurations
|
||||
* @ingroup PJMEDIA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_CONFIG Compile time configuration
|
||||
* @ingroup PJMEDIA_BASE
|
||||
* @brief Some compile time configuration settings.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
* Types of sound stream backends.
|
||||
*/
|
||||
|
||||
/** Constant for NULL sound backend. */
|
||||
#define PJMEDIA_SOUND_NULL_SOUND 0
|
||||
|
||||
/** Constant for PortAudio sound backend. */
|
||||
#define PJMEDIA_SOUND_PORTAUDIO_SOUND 1
|
||||
|
||||
/** Constant for Win32 DirectSound sound backend. */
|
||||
#define PJMEDIA_SOUND_WIN32_DIRECT_SOUND 2
|
||||
|
||||
|
||||
|
@ -132,6 +154,10 @@
|
|||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_CONFIG_H__ */
|
||||
|
||||
|
|
|
@ -34,71 +34,295 @@
|
|||
*/
|
||||
|
||||
/**
|
||||
* @mainpage Welcome to PJMEDIA!
|
||||
* @mainpage PJMEDIA and PJMEDIA-CODEC
|
||||
*
|
||||
* @section intro_sec What is PJMEDIA
|
||||
* \n
|
||||
* @section intro_sec PJMEDIA
|
||||
*
|
||||
* PJMEDIA open source (GPL) library contains objects that implements multimedia
|
||||
* capabilities. It can be used with signaling libraries such as PJSIP to create
|
||||
* a complete multimedia communication endpoint.
|
||||
* PJMEDIA is a rather complete media stack, distributed under Open Source/GPL
|
||||
* terms, and featuring small footprint and good extensibility and portability.
|
||||
*
|
||||
* Please click the <A HREF="modules.htm"><b>Modules</b></A> link on top
|
||||
* of this page to get the complete features currently present in PJMEDIA.
|
||||
*
|
||||
* Also please read the documentation about @ref PJMEDIA_PORT_CONCEPT,
|
||||
* which is a major concept that is used for implementing many objects in
|
||||
* the library.
|
||||
*
|
||||
* \n
|
||||
* @section pjmedia_codec_sec PJMEDIA-CODEC
|
||||
*
|
||||
* PJMEDIA-CODEC is a static library containing various codec implementations,
|
||||
* wrapped into PJMEDIA codec framework. The static library is designed as
|
||||
* such so that only codecs that are explicitly initialized are linked with
|
||||
* the application, therefore keeping the application size in control.
|
||||
*
|
||||
* Please see @ref pjmedia_codec_page on how to use the codec in
|
||||
* PJMEDIA-CODEC.
|
||||
*
|
||||
* \n
|
||||
* @section pjmedia_lic Copying and Acknowledgements
|
||||
*
|
||||
* Please see @ref lic_stuffs page for the details.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @page pjmedia_codec_page Using PJMEDIA-CODEC
|
||||
*
|
||||
* Before application can use a codec, it needs to initialize and register
|
||||
* the codec to the codec manager. This is accomplished with using
|
||||
* constructs like the following:
|
||||
*
|
||||
\code
|
||||
#include <pjmedia.h>
|
||||
#include <pjmedia-codec.h>
|
||||
|
||||
init_codecs( pjmedia_endpt *med_ept )
|
||||
{
|
||||
// Register G.711 codecs
|
||||
pjmedia_codec_g711_init(med_ept);
|
||||
|
||||
// Register GSM codec.
|
||||
pjmedia_codec_gsm_init(med_ept);
|
||||
|
||||
// Register Speex codecs.
|
||||
// With the default flag, this will register three codecs:
|
||||
// speex/8000, speex/16000, and speex/32000
|
||||
pjmedia_codec_speex_init(med_ept, 0, 0, 0);
|
||||
}
|
||||
\endcode
|
||||
*
|
||||
* After the codec is registered, application may create the encoder/decoder
|
||||
* instance, by using the API as documented in @ref PJMEDIA_CODEC.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @page lic_stuffs Copying and Acknowledgements
|
||||
* @section lic_stuff Copying and Acknowledgements
|
||||
* @subsection pjmedia_about_subsec About PJMEDIA
|
||||
*
|
||||
* <pre>
|
||||
* Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
* </pre>
|
||||
* PJMEDIA is distributed under GPL terms (other licensing schemes may be
|
||||
* arranged):
|
||||
\verbatim
|
||||
Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
\endverbatim
|
||||
*
|
||||
*
|
||||
* @subsection portaudio_subsec About PortAudio
|
||||
* @section other_acks Acknowlegments
|
||||
* @subsection portaudio_subsec PortAudio
|
||||
*
|
||||
* PortAudio is an excellent sound device library that is chosen as sound
|
||||
* device abstraction in PJMEDIA. It has the following characteristics that
|
||||
* makes it perfect for our use:
|
||||
*
|
||||
* - It is portable and complete
|
||||
*\n
|
||||
* It supports multiple back-ends on Windows, Windows CE (WinCE)/PocketPC,
|
||||
* Linux, Unix, and MacOS. More platforms may be supported.
|
||||
* - It is callback based
|
||||
*\n
|
||||
* The callback based for supplying/retrieving frames from the audio
|
||||
* device is perfect for our use.
|
||||
* - No nonsense, C based library.
|
||||
* - Actively maintained.
|
||||
* PortAudio is supported as one of the sound device backend, and
|
||||
* is used by default on Linux/Unix and MacOS X target.
|
||||
*
|
||||
* Please visit http://www.portaudio.com for more info.
|
||||
* Please visit <A HREF="http://www.portaudio.com">http://www.portaudio.com</A>
|
||||
* for more info.
|
||||
*
|
||||
* PortAudio is distributed with the following condition.
|
||||
* <pre>
|
||||
* Based on the Open Source API proposed by Ross Bencina
|
||||
* Copyright (c) 1999-2000 Phil Burk
|
||||
\verbatim
|
||||
Based on the Open Source API proposed by Ross Bencina
|
||||
Copyright (c) 1999-2000 Phil Burk
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
\endverbatim
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files
|
||||
* (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge,
|
||||
* publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
* </pre>
|
||||
* @subsection resample_ack Resample
|
||||
*
|
||||
* PJMEDIA uses <tt>resample-1.8.tar.gz</tt> from
|
||||
* <A HREF="http://www-ccrma.stanford.edu/~jos/resample/">
|
||||
* Digital Audio Resampling Home Page</A>. This library is distibuted
|
||||
* on LGPL terms.
|
||||
*
|
||||
* Some excerpts from the original source codes:
|
||||
\verbatim
|
||||
HISTORY
|
||||
|
||||
The first version of this software was written by Julius O. Smith III
|
||||
<jos@ccrma.stanford.edu> at CCRMA <http://www-ccrma.stanford.edu> in
|
||||
1981. It was called SRCONV and was written in SAIL for PDP-10
|
||||
compatible machines. The algorithm was first published in
|
||||
|
||||
Smith, Julius O. and Phil Gossett. ``A Flexible Sampling-Rate
|
||||
Conversion Method,'' Proceedings (2): 19.4.1-19.4.4, IEEE Conference
|
||||
on Acoustics, Speech, and Signal Processing, San Diego, March 1984.
|
||||
|
||||
An expanded tutorial based on this paper is available at the Digital
|
||||
Audio Resampling Home Page given above.
|
||||
|
||||
Circa 1988, the SRCONV program was translated from SAIL to C by
|
||||
Christopher Lee Fraley working with Roger Dannenberg at CMU.
|
||||
|
||||
Since then, the C version has been maintained by jos.
|
||||
|
||||
Sndlib support was added 6/99 by John Gibson <jgg9c@virginia.edu>.
|
||||
|
||||
The resample program is free software distributed in accordance
|
||||
with the Lesser GNU Public License (LGPL). There is NO warranty; not
|
||||
even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
\endverbatim
|
||||
*
|
||||
* @subsection jb_ack Adaptive Jitter Buffer
|
||||
*
|
||||
* The PJMEDIA jitter buffer is based on implementation kindly donated
|
||||
* by <A HREF="http://www.switchlab.com">Switchlab, Ltd.</A>, and is
|
||||
* distributed under PJMEDIA licensing terms.
|
||||
*
|
||||
*
|
||||
* @subsection silence_det_ack Adaptive Silence Detector
|
||||
*
|
||||
* The adaptive silence detector was based on silence detector
|
||||
* implementation in <A HREF="http://www.openh323.org">Open H323</A>
|
||||
* project. I couldn't find the source code anymore, but generally
|
||||
* Open H323 files are distributed under MPL terms and has the
|
||||
* following excerpts:
|
||||
\verbatim
|
||||
Open H323 Library
|
||||
|
||||
Copyright (c) 1998-2000 Equivalence Pty. Ltd.
|
||||
|
||||
The contents of this file are subject to the Mozilla Public License
|
||||
Version 1.0 (the "License"); you may not use this file except in
|
||||
compliance with the License. You may obtain a copy of the License at
|
||||
http://www.mozilla.org/MPL/
|
||||
|
||||
Software distributed under the License is distributed on an "AS IS"
|
||||
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
||||
the License for the specific language governing rights and limitations
|
||||
under the License.
|
||||
|
||||
The Original Code is Open H323 Library.
|
||||
|
||||
The Initial Developer of the Original Code is Equivalence Pty. Ltd.
|
||||
|
||||
Portions of this code were written with the assisance of funding from
|
||||
Vovida Networks, Inc. http://www.vovida.com.
|
||||
\endverbatim
|
||||
|
||||
* @subsection gsm_ack GSM Codec
|
||||
*
|
||||
* PJMEDIA uses GSM
|
||||
* <A HREF="http://kbs.cs.tu-berlin.de/~jutta/toast.html">GSM 06.10</A>
|
||||
* version 1.0 at patchlevel 12. It has the following Copyright notice:
|
||||
*
|
||||
\verbatim
|
||||
Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universitaet Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
are deemed to have made any representations as to the suitability of this
|
||||
software for any purpose nor are held responsible for any defects of
|
||||
this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
\endverbatim
|
||||
*
|
||||
*
|
||||
* @subsection speex_codec_ack Speex Codec
|
||||
*
|
||||
* PJMEDIA uses Speex codec uses version 1.1.12 from <A HREF="http://www.speex.org">
|
||||
* www.speex.org</A>. The Speex library comes with the following Copying
|
||||
* notice:
|
||||
\verbatim
|
||||
Copyright 2002-2005
|
||||
Xiph.org Foundation
|
||||
Jean-Marc Valin
|
||||
David Rowe
|
||||
EpicGames
|
||||
Analog Devices
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
\endverbatim
|
||||
*
|
||||
*
|
||||
* @subsection g711_codec_ack G.711 Codec
|
||||
*
|
||||
* The G.711 codec algorithm came from Sun Microsystems, Inc, and it's
|
||||
* got the following excerpts:
|
||||
*
|
||||
\verbatim
|
||||
This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
for unrestricted use. Users may copy or modify this source code without
|
||||
charge.
|
||||
|
||||
SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
|
||||
Sun source code is provided with no support and without any obligation on
|
||||
the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
modification or enhancement.
|
||||
|
||||
SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
OR ANY PART THEREOF.
|
||||
|
||||
In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
or profits or other special, indirect and consequential damages, even if
|
||||
Sun has been advised of the possibility of such damages.
|
||||
|
||||
Sun Microsystems, Inc.
|
||||
2550 Garcia Avenue
|
||||
Mountain View, California 94043
|
||||
\endverbatim
|
||||
*
|
||||
*/
|
||||
|
||||
#endif /* __PJMEDIA_DOXYGEN_H__ */
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* @brief Media endpoint.
|
||||
*/
|
||||
/**
|
||||
* @defgroup PJMED_ENDPT Multimedia Endpoint
|
||||
* @defgroup PJMED_ENDPT The Endpoint
|
||||
* @ingroup PJMEDIA
|
||||
* @{
|
||||
*
|
||||
|
|
|
@ -19,9 +19,22 @@
|
|||
#ifndef __PJMEDIA_ERRNO_H__
|
||||
#define __PJMEDIA_ERRNO_H__
|
||||
|
||||
/**
|
||||
* @file errno.h Error Codes
|
||||
* @brief PJMEDIA specific error codes.
|
||||
*/
|
||||
|
||||
#include <pjmedia/types.h>
|
||||
#include <pj/errno.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_ERRNO Error Codes
|
||||
* @ingroup PJMEDIA_BASE
|
||||
* @brief PJMEDIA specific error codes.
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
|
@ -31,12 +44,12 @@ PJ_BEGIN_DECL
|
|||
#define PJMEDIA_ERRNO_START (PJ_ERRNO_START_USER + PJ_ERRNO_SPACE_SIZE)
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* Mapping from PortAudio error codes to pjmedia error space.
|
||||
*/
|
||||
#define PJMEDIA_PORTAUDIO_ERRNO_START (PJMEDIA_ERRNO_START+PJ_ERRNO_SPACE_SIZE-1000)
|
||||
|
||||
/*
|
||||
/**
|
||||
* Convert PortAudio error code to PJMEDIA error code.
|
||||
*/
|
||||
#define PJMEDIA_ERRNO_FROM_PORTAUDIO(err) (err+PJMEDIA_PORTAUDIO_ERRNO_START)
|
||||
|
@ -388,11 +401,6 @@ PJ_BEGIN_DECL
|
|||
#define PJMEDIA_RTP_ENOCONFIG (PJMEDIA_ERRNO_START+134) /* 220134 */
|
||||
|
||||
|
||||
/************************************************************
|
||||
* JITTER BUFFER ERRORS
|
||||
***********************************************************/
|
||||
|
||||
|
||||
/************************************************************
|
||||
* PORT ERRORS
|
||||
***********************************************************/
|
||||
|
@ -486,5 +494,10 @@ PJ_BEGIN_DECL
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_ERRNO_H__ */
|
||||
|
||||
|
|
|
@ -19,8 +19,22 @@
|
|||
#ifndef __PJMEDIA_G711_H__
|
||||
#define __PJMEDIA_G711_H__
|
||||
|
||||
/**
|
||||
* @file g711.h
|
||||
* @brief G711 Codec
|
||||
*/
|
||||
|
||||
#include <pjmedia-codec/types.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_G711 G711
|
||||
* @ingroup PJMEDIA_CODEC
|
||||
* @brief Standard G.711/PCMA and PCMU codec.
|
||||
* @{
|
||||
* This section describes functions to register and register G.711 codec
|
||||
* factory to the codec manager. After the codec factory has been registered,
|
||||
* application can use @ref PJMEDIA_CODEC API to manipulate the codec.
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
@ -47,6 +61,9 @@ PJ_DECL(pj_status_t) pjmedia_codec_g711_deinit(void);
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* __PJMEDIA_G711_H__ */
|
||||
|
||||
|
|
|
@ -31,9 +31,15 @@
|
|||
|
||||
/**
|
||||
* @defgroup PJMED_JBUF Adaptive jitter buffer
|
||||
* @ingroup PJMEDIA
|
||||
* @ingroup PJMEDIA_FRAME_OP
|
||||
* @{
|
||||
* This section describes PJMEDIA's implementation of de-jitter buffer.
|
||||
* The de-jitter buffer may be set to operate in adaptive mode or fixed
|
||||
* delay mode.
|
||||
*
|
||||
* The jitter buffer is also able to report the status of the current
|
||||
* frame (#pjmedia_jb_frame_type). This status is used for examply by
|
||||
* @ref PJMED_STRM to invoke the codec's @ref PJMED_PLC algorithm.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -26,22 +26,40 @@
|
|||
*/
|
||||
#include <pjmedia/port.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_MASTER_PORT Master Port
|
||||
* @ingroup PJMEDIA_PORT_CLOCK
|
||||
* @brief Provides media clock for media ports.
|
||||
* @{
|
||||
* A master port has two media ports connected to it, and by convention
|
||||
* thay are called downstream and upstream ports. The media stream flowing to
|
||||
* the downstream port is called encoding or send direction, and media stream
|
||||
* flowing to the upstream port is called decoding or receive direction
|
||||
* (imagine the downstream as stream to remote endpoint, and upstream as
|
||||
* local media port; media flowing to remote endpoint (downstream) will need
|
||||
* to be encoded before it is transmitted to remote endpoint).
|
||||
*
|
||||
* A master port internally has an instance of @ref PJMEDIA_CLOCK, which
|
||||
* provides the essensial timing for the master port. The @ref PJMEDIA_CLOCK
|
||||
* runs asynchronously, and whenever a clock <b>tick</b> expires, a callback
|
||||
* will be called, and the master port performs the following tasks:
|
||||
* - it calls <b><tt>get_frame()</tt></b> from the downstream port,
|
||||
* when give the frame to the upstream port by calling <b><tt>put_frame
|
||||
* </tt></b> to the upstream port, and
|
||||
* - performs the same task, but on the reverse direction (i.e. get the stream
|
||||
* from upstream port and give it to the downstream port).
|
||||
*
|
||||
* Because master port enables media stream to flow automatically, it is
|
||||
* said that the master port supplies @ref PJMEDIA_PORT_CLOCK to the
|
||||
* media ports interconnection.
|
||||
*
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
/**
|
||||
* Opaque declaration for master port.
|
||||
* A master port has two media ports connected to it, i.e. downstream and
|
||||
* upstream ports. The media stream flowing to the downstream port is called
|
||||
* encoding or send direction, and media stream flowing to the upstream port
|
||||
* is called decoding or receive direction.
|
||||
*
|
||||
* A master port has a "clock" that periodically passes the media frame from
|
||||
* downstream to upstream ports, and vice versa. In each run, it retrieves
|
||||
* media frame from one side with #pjmedia_port_get_frame(), and passes the
|
||||
* media frame to the other side with #pjmedia_port_put_frame(). In each run,
|
||||
* this process is done for twice, i.e. one for each direction.
|
||||
*/
|
||||
typedef struct pjmedia_master_port pjmedia_master_port;
|
||||
|
||||
|
@ -149,6 +167,10 @@ PJ_DECL(pj_status_t) pjmedia_master_port_destroy(pjmedia_master_port *m,
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_MASTER_PORT_H__ */
|
||||
|
||||
|
|
|
@ -26,12 +26,22 @@
|
|||
#include <pjmedia/port.h>
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_NULL_PORT Null Port
|
||||
* @ingroup PJMEDIA_PORT
|
||||
* @brief Null port is the simplest type of port.
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
/**
|
||||
* Create Null port.
|
||||
*
|
||||
* @param pool Pool to allocate memory.
|
||||
* @param sampling_rate Sampling rate of the port.
|
||||
* @param channel_count Number of channels.
|
||||
* @param samples_per_frame Number of samples per frame.
|
||||
|
@ -51,5 +61,9 @@ PJ_DECL(pj_status_t) pjmedia_null_port_create( pj_pool_t *pool,
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_NULL_PORT_H__ */
|
||||
|
|
|
@ -28,9 +28,18 @@
|
|||
|
||||
/**
|
||||
* @defgroup PJMED_PLC Packet Lost Concealment
|
||||
* @ingroup PJMEDIA
|
||||
* @ingroup PJMEDIA_FRAME_OP
|
||||
* @{
|
||||
* This section describes PJMEDIA's implementation of Packet Lost
|
||||
* Concealment algorithm. This algorithm is used to implement PLC for
|
||||
* codecs that do not have built-in support for one (e.g. G.711 or GSM codecs).
|
||||
*
|
||||
* The PLC algorithm (either built-in or external) is embedded in
|
||||
* PJMEDIA codec instance, and application can conceal lost frames
|
||||
* by calling <b><tt>recover()</tt></b> member of the codec's member
|
||||
* operation (#pjmedia_codec_op).
|
||||
*
|
||||
* See also @ref plc_codec for more info.
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -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__ */
|
||||
|
||||
|
|
|
@ -22,12 +22,21 @@
|
|||
|
||||
|
||||
/**
|
||||
* @file reample.h
|
||||
* @file resample.h
|
||||
* @brief Sample rate converter.
|
||||
*/
|
||||
#include <pjmedia/types.h>
|
||||
#include <pjmedia/port.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_RESAMPLE Resampling Algorithm
|
||||
* @ingroup PJMEDIA_FRAME_OP
|
||||
* @brief Functions to alter frame's clock rate.
|
||||
* @{
|
||||
* This section describes the base resampling functions. In addition to this,
|
||||
* application can use the @ref PJMEDIA_RESAMPLE_PORT which provides
|
||||
* media port abstraction for the base resampling algorithm.
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
@ -97,46 +106,83 @@ PJ_DECL(void) pjmedia_resample_run( pjmedia_resample *resample,
|
|||
PJ_DECL(unsigned) pjmedia_resample_get_input_size(pjmedia_resample *resample);
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_RESAMPLE_PORT Resample Port
|
||||
* @ingroup PJMEDIA_PORT
|
||||
* @brief Media port interface to change media stream's sampling rate.
|
||||
* @{
|
||||
* This section describes media port abstractoin for @ref PJMEDIA_RESAMPLE.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Option flags that can be specified when creating resample port.
|
||||
*/
|
||||
enum pjmedia_resample_port_options
|
||||
{
|
||||
/**
|
||||
* Do not use high quality resampling algorithm, but use linear
|
||||
* algorithm instead.
|
||||
*/
|
||||
PJMEDIA_RESAMPLE_USE_LINEAR = 1,
|
||||
|
||||
/**
|
||||
* Use small filter workspace when high quality resampling is
|
||||
* used.
|
||||
*/
|
||||
PJMEDIA_RESAMPLE_USE_SMALL_FILTER = 2,
|
||||
|
||||
/**
|
||||
* Do not destroy downstream port when resample port is destroyed.
|
||||
*/
|
||||
PJMEDIA_RESAMPLE_DONT_DESTROY_DN = 4,
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a resample port. This creates a bidirectional resample session,
|
||||
* which will resample frames when the port's get_frame() and put_frame()
|
||||
* is called.
|
||||
*
|
||||
* When the resample port's get_frame() is called, this port will get
|
||||
* a frame from the downstream port and resample the frame to the upstream
|
||||
* port's clock rate before returning it to the caller.
|
||||
* a frame from the downstream port and resample the frame to the target
|
||||
* clock rate before returning it to the caller.
|
||||
*
|
||||
* When the resample port's put_frame() is called, this port will resample
|
||||
* the frame to the downstream's port clock rate before giving the frame
|
||||
* the frame to the downstream port's clock rate before giving the frame
|
||||
* to the downstream port.
|
||||
*
|
||||
* @param pool Pool to allocate the structure and buffers.
|
||||
* @param high_quality If true, then high quality conversion will be
|
||||
* used, at the expense of more CPU and memory,
|
||||
* because temporary buffer needs to be created.
|
||||
* @param large_filter If true, large filter size will be used.
|
||||
* @param downstream_rate The sampling rate of the downstream port.
|
||||
* @param upstream_rate The sampling rate of the upstream port.
|
||||
* @param channel_count The number of channels. This argument is only
|
||||
* used for the port information. It does not
|
||||
* change the behavior of the resample port.
|
||||
* @param samples_per_frame Number of samples per frame from the downstream
|
||||
* port.
|
||||
* @param dn_port The downstream port, which clock rate is to
|
||||
* be converted to the target clock rate.
|
||||
* @param clock_rate Target clock rate.
|
||||
* @param options Flags from #pjmedia_resample_port_options.
|
||||
* When this flag is zero, the default behavior
|
||||
* is to use high quality resampling with
|
||||
* large filter, and to destroy downstream port
|
||||
* when resample port is destroyed.
|
||||
* @param p_port Pointer to receive the resample port instance.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
PJ_DECL(pj_status_t) pjmedia_resample_port_create( pj_pool_t *pool,
|
||||
pj_bool_t high_quality,
|
||||
pj_bool_t large_filter,
|
||||
unsigned downstream_rate,
|
||||
unsigned upstream_rate,
|
||||
unsigned channel_count,
|
||||
unsigned samples_per_frame,
|
||||
pjmedia_port *dn_port,
|
||||
unsigned clock_rate,
|
||||
unsigned options,
|
||||
pjmedia_port **p_port );
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_RESAMPLE_H__ */
|
||||
|
||||
|
|
|
@ -32,8 +32,8 @@ PJ_BEGIN_DECL
|
|||
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_RTCP RTCP Management
|
||||
* @ingroup PJMEDIA
|
||||
* @defgroup PJMED_RTCP RTCP Session
|
||||
* @ingroup PJMEDIA_TRANSPORT
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
@ -218,6 +218,10 @@ struct pjmedia_rtcp_stat
|
|||
typedef struct pjmedia_rtcp_stat pjmedia_rtcp_stat;
|
||||
|
||||
|
||||
/**
|
||||
* The types for keeping the average jitter value. Ideally a floating point
|
||||
* number should be used, but this is not always available/desired.
|
||||
*/
|
||||
#if defined(PJ_HAS_FLOATING_POINT) && PJ_HAS_FLOATING_POINT!=0
|
||||
typedef double PJMEDIA_AVG_JITTER_TYPE;
|
||||
#else
|
||||
|
|
|
@ -31,15 +31,16 @@ PJ_BEGIN_DECL
|
|||
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_RTP RTP Packet and RTP Session Management
|
||||
* @ingroup PJMEDIA
|
||||
* @defgroup PJMED_RTP RTP Session
|
||||
* @ingroup PJMEDIA_TRANSPORT
|
||||
* @{
|
||||
*
|
||||
* The RTP module is designed to be dependent only to PJLIB, it does not depend
|
||||
* on any other parts of PJMEDIA library. The RTP module does not even depend
|
||||
* on any transports (sockets), to promote even more use.
|
||||
*
|
||||
* An RTCP implementation is available, in separate module.
|
||||
* An RTCP implementation is available, in separate module. Please see
|
||||
* @ref PJMED_RTCP.
|
||||
*
|
||||
* The functions that are provided by this module:
|
||||
* - creating RTP header for each outgoing packet.
|
||||
|
@ -129,9 +130,9 @@ typedef struct pjmedia_rtp_ext_hdr pjmedia_rtp_ext_hdr;
|
|||
*/
|
||||
struct pjmedia_rtp_dtmf_event
|
||||
{
|
||||
pj_uint8_t event;
|
||||
pj_uint8_t e_vol;
|
||||
pj_uint16_t duration;
|
||||
pj_uint8_t event; /**< Event type ID. */
|
||||
pj_uint8_t e_vol; /**< Event volume. */
|
||||
pj_uint16_t duration; /**< Event duration. */
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
|
||||
/**
|
||||
* @defgroup PJ_SDP SDP Parsing and Data Structure
|
||||
* @ingroup PJMEDIA
|
||||
* @defgroup PJMEDIA_SDP SDP Parsing and Data Structure
|
||||
* @ingroup PJMEDIA_SESSION
|
||||
* @{
|
||||
*
|
||||
* The basic SDP session descriptor and elements are described in header
|
||||
|
|
|
@ -25,8 +25,8 @@
|
|||
* @brief SDP negotiator header file.
|
||||
*/
|
||||
/**
|
||||
* @defgroup PJ_SDP_NEG SDP Negotiator.
|
||||
* @ingroup PJMEDIA
|
||||
* @defgroup PJMEDIA_SDP_NEG SDP Negotiator
|
||||
* @ingroup PJMEDIA_SESSION
|
||||
* @{
|
||||
*
|
||||
* The header file <b><pjmedia/sdp_neg.h></b> contains the declaration
|
||||
|
|
|
@ -32,8 +32,13 @@
|
|||
PJ_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_SES Media session
|
||||
* @defgroup PJMEDIA_SESSION Sessions
|
||||
* @ingroup PJMEDIA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_SES Media session
|
||||
* @ingroup PJMEDIA_SESSION
|
||||
* @{
|
||||
*
|
||||
* A media session represents multimedia communication between two
|
||||
|
@ -90,7 +95,6 @@ typedef struct pjmedia_session_info pjmedia_session_info;
|
|||
* @param si Session info structure to be initialized.
|
||||
* @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.
|
||||
*/
|
||||
|
@ -103,7 +107,7 @@ pjmedia_session_info_from_sdp( pj_pool_t *pool,
|
|||
const pjmedia_sdp_session *remote);
|
||||
|
||||
|
||||
/*
|
||||
/**
|
||||
* 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.
|
||||
|
@ -263,7 +267,7 @@ PJ_DECL(pj_status_t) pjmedia_session_get_port( pjmedia_session *session,
|
|||
*
|
||||
* @param session The media session.
|
||||
* @param index Stream index.
|
||||
* @param sta Stream statistic.
|
||||
* @param stat Stream statistic.
|
||||
*
|
||||
* @return PJ_SUCCESS on success.
|
||||
*/
|
||||
|
|
|
@ -26,6 +26,15 @@
|
|||
*/
|
||||
#include <pjmedia/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_SILENCEDET Adaptive Silence Detection
|
||||
* @ingroup PJMEDIA_FRAME_OP
|
||||
* @brief Adaptive Silence Detector
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
|
@ -179,5 +188,10 @@ unsigned char linear2ulaw(int pcm_val);
|
|||
PJ_END_DECL
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_SILENCE_DET_H__ */
|
||||
|
||||
|
|
|
@ -30,9 +30,34 @@
|
|||
PJ_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_SND Sound device abstraction.
|
||||
* @ingroup PJMEDIA
|
||||
* @defgroup PJMED_SND Sound Hardware Abstraction
|
||||
* @ingroup PJMED_SND_PORT
|
||||
* @brief PJMEDIA abstraction for sound device hardware
|
||||
* @{
|
||||
*
|
||||
* This section describes lower level abstraction for sound device
|
||||
* hardware. Application normally uses the higher layer @ref
|
||||
* PJMED_SND_PORT abstraction since it works seamlessly with
|
||||
* @ref PJMEDIA_PORT_CONCEPT.
|
||||
*
|
||||
* The sound hardware abstraction basically runs <b>asychronously</b>,
|
||||
* and application must register callbacks to be called to receive/
|
||||
* supply audio frames from/to the sound hardware.
|
||||
*
|
||||
* A full duplex sound stream (created with #pjmedia_snd_open())
|
||||
* requires application to supply two callbacks:
|
||||
* - <b><tt>rec_cb</tt></b> callback to be called when it has finished
|
||||
* capturing one media frame, and
|
||||
* - <b><tt>play_cb</tt></b> callback to be called when it needs media
|
||||
* frame to be played to the sound playback hardware.
|
||||
*
|
||||
* Half duplex sound stream (created with #pjmedia_snd_open_rec() or
|
||||
* #pjmedia_snd_open_player()) will only need one of the callback to
|
||||
* be specified.
|
||||
*
|
||||
* After sound stream is created, application need to call
|
||||
* #pjmedia_snd_stream_start() to start capturing/playing back media
|
||||
* frames from/to the sound device.
|
||||
*/
|
||||
|
||||
/** Opaque data type for audio stream. */
|
||||
|
@ -113,7 +138,8 @@ PJ_DECL(const pjmedia_snd_dev_info*) pjmedia_snd_get_dev_info(unsigned index);
|
|||
/**
|
||||
* Create sound stream for both capturing audio and audio playback, from the
|
||||
* same device. This is the recommended way to create simultaneous recorder
|
||||
* and player streams, because it should work on backends that does not allow
|
||||
* and player streams (instead of creating separate capture and playback
|
||||
* streams), because it works on backends that does not allow
|
||||
* a device to be opened more than once.
|
||||
*
|
||||
* @param rec_id Device index for recorder/capture stream, or
|
||||
|
|
|
@ -29,9 +29,36 @@
|
|||
PJ_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_SND_PORT Media Port Connection Abstraction to Sound Device
|
||||
* @ingroup PJMEDIA
|
||||
* @{
|
||||
* @defgroup PJMED_SND_PORT Sound Device Port
|
||||
* @ingroup PJMEDIA_PORT_CLOCK
|
||||
* @brief Media Port Connection Abstraction to the Sound Device
|
||||
@{
|
||||
|
||||
As explained in @ref PJMED_SND, the sound hardware abstraction provides
|
||||
some callbacks for its user:
|
||||
- it calls <b><tt>rec_cb</tt></b> callback when it has finished capturing
|
||||
one media frame, and
|
||||
- it calls <b><tt>play_cb</tt></b> when it needs media frame to be
|
||||
played to the sound playback hardware.
|
||||
|
||||
The @ref PJMED_SND_PORT (the object being explained here) add a
|
||||
thin wrapper to the hardware abstraction:
|
||||
- it will call downstream port's <tt>put_frame()</tt>
|
||||
when <b><tt>rec_cb()</tt></b> is called (i.e. when the sound hardware
|
||||
has finished capturing frame), and
|
||||
- it will call downstream port's <tt>get_frame()</tt> when
|
||||
<b><tt>play_cb()</tt></b> is called (i.e. every time the
|
||||
sound hardware needs more frames to be played to the playback hardware).
|
||||
|
||||
This simple abstraction enables media to flow automatically (and
|
||||
in timely manner) from the downstream media port to the sound device.
|
||||
In other words, the sound device port supplies media clock to
|
||||
the ports. The media clock concept is explained in @ref PJMEDIA_PORT_CLOCK
|
||||
section.
|
||||
|
||||
Application registers downstream port to the sound device port by
|
||||
calling #pjmedia_snd_port_connect();
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -168,6 +195,7 @@ PJ_DECL(pjmedia_snd_stream*) pjmedia_snd_port_get_snd_stream(
|
|||
* samples per frame, and bits per sample as the sound device port.
|
||||
*
|
||||
* @param snd_port The sound device port.
|
||||
* @param port The media port to be connected.
|
||||
*
|
||||
* @return PJ_SUCCESS on success, or the appropriate error
|
||||
* code.
|
||||
|
|
|
@ -30,27 +30,48 @@
|
|||
#include <pjmedia/endpoint.h>
|
||||
#include <pjmedia/port.h>
|
||||
#include <pjmedia/rtcp.h>
|
||||
#include <pjmedia/transport.h>
|
||||
#include <pj/sock.h>
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMED_STRM Media Stream
|
||||
* @ingroup PJMEDIA
|
||||
* @defgroup PJMED_STRM Streams
|
||||
* @ingroup PJMEDIA_PORT
|
||||
* @brief Media port for communicating with remote peer via the network.
|
||||
* @{
|
||||
*
|
||||
* A media stream is a bidirectional multimedia communication between two
|
||||
* endpoints. It corresponds to a media description (m= line) in SDP.
|
||||
* endpoints. It corresponds to a media description (m= line) in SDP
|
||||
* session descriptor.
|
||||
*
|
||||
* A media stream consists of two unidirectional channels:
|
||||
* - encoding channel, which transmits unidirectional media to remote, and
|
||||
* - decoding channel, which receives unidirectional media from remote.
|
||||
*
|
||||
* Application normally does not need to create the stream directly; it
|
||||
* creates media session instead. The media session will create the media
|
||||
* streams as necessary, according to the media descriptors that present
|
||||
* in local and remote SDP.
|
||||
* A media stream exports media port interface (see @ref PJMEDIA_PORT_CONCEPT)
|
||||
* and application normally uses this interface to interconnect the stream
|
||||
* to other PJMEDIA components.
|
||||
*
|
||||
* A media stream internally manages the following objects:
|
||||
* - an instance of media codec (see @ref PJMEDIA_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 media transport to send and receive packets
|
||||
* to/from the network (see @ref PJMEDIA_TRANSPORT_H).
|
||||
*
|
||||
* Streams are created by calling #pjmedia_stream_create(), specifying
|
||||
* #pjmedia_stream_info structure in the parameter. Application can construct
|
||||
* the #pjmedia_stream_info structure manually, or use
|
||||
* #pjmedia_stream_info_from_sdp() or #pjmedia_session_info_from_sdp()
|
||||
* functions to construct the #pjmedia_stream_info from local and remote
|
||||
* SDP session descriptors.
|
||||
*
|
||||
* Application can also use @ref PJMEDIA_SESSION to indirectly create the
|
||||
* streams.
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -92,89 +113,6 @@ struct pjmedia_stream_info
|
|||
typedef struct pjmedia_stream_info pjmedia_stream_info;
|
||||
|
||||
|
||||
/**
|
||||
* Opaque declaration for media stream.
|
||||
*/
|
||||
typedef struct pjmedia_stream pjmedia_stream;
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_transport_op.
|
||||
*/
|
||||
typedef struct pjmedia_transport pjmedia_transport;
|
||||
|
||||
|
||||
/**
|
||||
* This structure describes the operations for the stream transport.
|
||||
*/
|
||||
struct pjmedia_transport_op
|
||||
{
|
||||
/**
|
||||
* This function is called by the stream when the transport is about
|
||||
* to be used by the stream for the first time, and it tells the transport
|
||||
* about remote RTP address to send the packet and some callbacks to be
|
||||
* called for incoming packets.
|
||||
*/
|
||||
pj_status_t (*attach)(pjmedia_transport *tp,
|
||||
pjmedia_stream *strm,
|
||||
const pj_sockaddr_t *rem_addr,
|
||||
unsigned addr_len,
|
||||
void (*rtp_cb)(pjmedia_stream*,
|
||||
const void*,
|
||||
pj_ssize_t),
|
||||
void (*rtcp_cb)(pjmedia_stream*,
|
||||
const void*,
|
||||
pj_ssize_t));
|
||||
|
||||
/**
|
||||
* This function is called by the stream when the stream is no longer
|
||||
* need the transport (normally when the stream is about to be closed).
|
||||
*/
|
||||
void (*detach)(pjmedia_transport *tp,
|
||||
pjmedia_stream *strm);
|
||||
|
||||
/**
|
||||
* This function is called by the stream to send RTP packet using the
|
||||
* transport.
|
||||
*/
|
||||
pj_status_t (*send_rtp)(pjmedia_transport *tp,
|
||||
const void *pkt,
|
||||
pj_size_t size);
|
||||
|
||||
/**
|
||||
* This function is called by the stream to send RTCP packet using the
|
||||
* transport.
|
||||
*/
|
||||
pj_status_t (*send_rtcp)(pjmedia_transport *tp,
|
||||
const void *pkt,
|
||||
pj_size_t size);
|
||||
|
||||
/**
|
||||
* This function can be called to destroy this transport.
|
||||
*/
|
||||
pj_status_t (*destroy)(pjmedia_transport *tp);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_transport_op.
|
||||
*/
|
||||
typedef struct pjmedia_transport_op pjmedia_transport_op;
|
||||
|
||||
|
||||
/**
|
||||
* This structure declares stream transport. A stream transport is called
|
||||
* by the stream to transmit a packet, and will notify stream when
|
||||
* incoming packet is arrived.
|
||||
*/
|
||||
struct pjmedia_transport
|
||||
{
|
||||
char name[PJ_MAX_OBJ_NAME];
|
||||
|
||||
pjmedia_transport_op *op;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a media stream based on the specified parameter. After the stream
|
||||
|
|
|
@ -0,0 +1,140 @@
|
|||
/* $Id$ */
|
||||
/*
|
||||
* Copyright (C) 2003-2006 Benny Prijono <benny@prijono.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef __PJMEDIA_TRANSPORT_H__
|
||||
#define __PJMEDIA_TRANSPORT_H__
|
||||
|
||||
|
||||
/**
|
||||
* @file transport.h Media Transport Interface
|
||||
* @brief Transport interface.
|
||||
*/
|
||||
|
||||
#include <pjmedia/types.h>
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_TRANSPORT Transports
|
||||
* @ingroup PJMEDIA
|
||||
* @brief Transports.
|
||||
* Transport related components.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_TRANSPORT_H Network Transport Interface
|
||||
* @ingroup PJMEDIA_TRANSPORT
|
||||
* @brief PJMEDIA object for sending/receiving media packets over the network
|
||||
* @{
|
||||
* The media transport (#pjmedia_transport) is the object to send and
|
||||
* receive media packets over the network. Currently only media @ref PJMED_STRM
|
||||
* are using the transport.
|
||||
*
|
||||
* Although currently only @ref PJMEDIA_TRANSPORT_UDP is implemented,
|
||||
* media transport interface is intended to support any custom transports.
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
/*
|
||||
* Forward declaration for media transport.
|
||||
*/
|
||||
typedef struct pjmedia_transport pjmedia_transport;
|
||||
|
||||
|
||||
/**
|
||||
* This structure describes the operations for the stream transport.
|
||||
*/
|
||||
struct pjmedia_transport_op
|
||||
{
|
||||
/**
|
||||
* This function is called by the stream when the transport is about
|
||||
* to be used by the stream for the first time, and it tells the transport
|
||||
* about remote RTP address to send the packet and some callbacks to be
|
||||
* called for incoming packets.
|
||||
*/
|
||||
pj_status_t (*attach)(pjmedia_transport *tp,
|
||||
pjmedia_stream *strm,
|
||||
const pj_sockaddr_t *rem_addr,
|
||||
unsigned addr_len,
|
||||
void (*rtp_cb)(pjmedia_stream*,
|
||||
const void*,
|
||||
pj_ssize_t),
|
||||
void (*rtcp_cb)(pjmedia_stream*,
|
||||
const void*,
|
||||
pj_ssize_t));
|
||||
|
||||
/**
|
||||
* This function is called by the stream when the stream is no longer
|
||||
* need the transport (normally when the stream is about to be closed).
|
||||
*/
|
||||
void (*detach)(pjmedia_transport *tp,
|
||||
pjmedia_stream *strm);
|
||||
|
||||
/**
|
||||
* This function is called by the stream to send RTP packet using the
|
||||
* transport.
|
||||
*/
|
||||
pj_status_t (*send_rtp)(pjmedia_transport *tp,
|
||||
const void *pkt,
|
||||
pj_size_t size);
|
||||
|
||||
/**
|
||||
* This function is called by the stream to send RTCP packet using the
|
||||
* transport.
|
||||
*/
|
||||
pj_status_t (*send_rtcp)(pjmedia_transport *tp,
|
||||
const void *pkt,
|
||||
pj_size_t size);
|
||||
|
||||
/**
|
||||
* This function can be called to destroy this transport.
|
||||
*/
|
||||
pj_status_t (*destroy)(pjmedia_transport *tp);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @see pjmedia_transport_op.
|
||||
*/
|
||||
typedef struct pjmedia_transport_op pjmedia_transport_op;
|
||||
|
||||
|
||||
/**
|
||||
* This structure declares stream transport. A stream transport is called
|
||||
* by the stream to transmit a packet, and will notify stream when
|
||||
* incoming packet is arrived.
|
||||
*/
|
||||
struct pjmedia_transport
|
||||
{
|
||||
/** Transport name (for logging purpose). */
|
||||
char name[PJ_MAX_OBJ_NAME];
|
||||
|
||||
/** Transport's "virtual" function table. */
|
||||
pjmedia_transport_op *op;
|
||||
};
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_TRANSPORT_H__ */
|
||||
|
|
@ -21,13 +21,23 @@
|
|||
|
||||
|
||||
/**
|
||||
* @file stream_transport_udp.h
|
||||
* @file transport_udp.h
|
||||
* @brief Stream transport with UDP.
|
||||
*/
|
||||
|
||||
#include <pjmedia/stream.h>
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_TRANSPORT_UDP UDP Socket Transport
|
||||
* @ingroup PJMEDIA_TRANSPORT_H
|
||||
* @brief Implementation of media transport with UDP sockets.
|
||||
* @{
|
||||
*/
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
/**
|
||||
* Options that can be specified when creating UDP transport.
|
||||
*/
|
||||
|
@ -92,6 +102,13 @@ PJ_DECL(pj_status_t) pjmedia_transport_udp_close(pjmedia_transport *tp);
|
|||
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_TRANSPORT_UDP_H__ */
|
||||
|
||||
|
|
|
@ -19,15 +19,37 @@
|
|||
#ifndef __PJMEDIA_TYPES_H__
|
||||
#define __PJMEDIA_TYPES_H__
|
||||
|
||||
/**
|
||||
* @file pjmedia/types.h Basic Types
|
||||
* @brief Basic PJMEDIA types.
|
||||
*/
|
||||
|
||||
#include <pjmedia/config.h>
|
||||
#include <pj/sock.h> /* pjmedia_sock_info */
|
||||
#include <pj/string.h> /* pj_memcpy(), pj_memset() */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_FRAME_OP Frame Operations
|
||||
* @ingroup PJMEDIA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_MISC Misc
|
||||
* @ingroup PJMEDIA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_TYPES Basic Types
|
||||
* @ingroup PJMEDIA_BASE
|
||||
* @brief Basic PJMEDIA types and operations.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Top most media type.
|
||||
*/
|
||||
enum pjmedia_type
|
||||
typedef enum pjmedia_type
|
||||
{
|
||||
/** No type. */
|
||||
PJMEDIA_TYPE_NONE = 0,
|
||||
|
@ -43,19 +65,14 @@ enum pjmedia_type
|
|||
*/
|
||||
PJMEDIA_TYPE_UNKNOWN = 3,
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @see pjmedia_type
|
||||
*/
|
||||
typedef enum pjmedia_type pjmedia_type;
|
||||
} pjmedia_type;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Media direction.
|
||||
*/
|
||||
enum pjmedia_dir
|
||||
typedef enum pjmedia_dir
|
||||
{
|
||||
/** None */
|
||||
PJMEDIA_DIR_NONE = 0,
|
||||
|
@ -69,12 +86,8 @@ enum pjmedia_dir
|
|||
/** Incoming and outgoing stream. */
|
||||
PJMEDIA_DIR_ENCODING_DECODING = 3,
|
||||
|
||||
};
|
||||
} pjmedia_dir;
|
||||
|
||||
/**
|
||||
* @see pjmedia_dir
|
||||
*/
|
||||
typedef enum pjmedia_dir pjmedia_dir;
|
||||
|
||||
|
||||
/* Alternate names for media direction: */
|
||||
|
@ -95,22 +108,50 @@ typedef enum pjmedia_dir pjmedia_dir;
|
|||
#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)
|
||||
|
||||
|
||||
/**
|
||||
* Opague declaration of media endpoint.
|
||||
*/
|
||||
typedef struct pjmedia_endpt pjmedia_endpt;
|
||||
|
||||
|
||||
/*
|
||||
* Forward declaration for stream (needed by transport).
|
||||
*/
|
||||
typedef struct pjmedia_stream pjmedia_stream;
|
||||
|
||||
|
||||
/**
|
||||
* Media socket info.
|
||||
* 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;
|
||||
|
||||
pj_sock_t rtp_sock; /**< Socket for RTP. */
|
||||
pj_sockaddr_in rtp_addr_name; /**< Local RTP address to be advertised.*/
|
||||
pj_sock_t rtcp_sock; /**< Socket for RTCP. */
|
||||
pj_sockaddr_in rtcp_addr_name; /**< Local RTCP addr to be advertised. */
|
||||
/** 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_in 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_in rtcp_addr_name;
|
||||
|
||||
} pjmedia_sock_info;
|
||||
|
||||
|
@ -162,5 +203,10 @@ PJ_INLINE(void) pjmedia_copy_samples(pj_int16_t *dst, const pj_int16_t *src,
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_TYPES_H__ */
|
||||
|
||||
|
|
|
@ -30,6 +30,26 @@
|
|||
PJ_BEGIN_DECL
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_FILE_PLAY File Player
|
||||
* @ingroup PJMEDIA_PORT
|
||||
* @brief WAV File Player
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* WAV file player options.
|
||||
*/
|
||||
enum pjmedia_file_player_option
|
||||
{
|
||||
/**
|
||||
* Tell the file player to return NULL frame when the whole
|
||||
* file has been played.
|
||||
*/
|
||||
PJMEDIA_FILE_NO_LOOP = 1,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a media port to play streams from a WAV file.
|
||||
*
|
||||
|
@ -39,7 +59,7 @@ PJ_BEGIN_DECL
|
|||
* from this port. If the value is zero, the default
|
||||
* duration (20ms) will be used.
|
||||
* @param flags Port creation flags.
|
||||
* @param buf_size Buffer size to be allocated. If the value is zero or
|
||||
* @param buff_size Buffer size to be allocated. If the value is zero or
|
||||
* negative, the port will use default buffer size (which
|
||||
* is about 4KB).
|
||||
* @param user_data User data to be associated with the file player port.
|
||||
|
@ -68,19 +88,33 @@ PJ_DECL(pj_status_t) pjmedia_wav_player_port_set_pos( pjmedia_port *port,
|
|||
pj_uint32_t samples );
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_FILE_REC File Writer (Recorder)
|
||||
* @ingroup PJMEDIA_PORT
|
||||
* @brief WAV File Writer (Recorder)
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a media port to record streams to a WAV file. Note that the port
|
||||
* must be closed properly (with #pjmedia_port_destroy()) so that the WAV
|
||||
* header can be filled with correct values (such as the file length).
|
||||
*
|
||||
* @param pool Pool to create memory buffers for this port.
|
||||
* @param filename File name.
|
||||
* @param clock_rate The sampling rate.
|
||||
* @param channel_count Number of channels.
|
||||
* @param pool Pool to create memory buffers for this port.
|
||||
* @param filename File name.
|
||||
* @param clock_rate The sampling rate.
|
||||
* @param channel_count Number of channels.
|
||||
* @param samples_per_frame Number of samples per frame.
|
||||
* @param bits_per_sampe Number of bits per sample (eg 16).
|
||||
* @param flags Port creation flags (must be 0 at present).
|
||||
* @param buf_size Buffer size to be allocated. If the value is zero or
|
||||
* @param bits_per_sample Number of bits per sample (eg 16).
|
||||
* @param flags Port creation flags (must be 0 at present).
|
||||
* @param buff_size Buffer size to be allocated. If the value is zero or
|
||||
* negative, the port will use default buffer size (which
|
||||
* is about 4KB).
|
||||
* @param user_data User data to be associated with the file writer port.
|
||||
|
@ -101,6 +135,10 @@ PJ_DECL(pj_status_t) pjmedia_wav_writer_port_create(pj_pool_t *pool,
|
|||
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
PJ_END_DECL
|
||||
|
||||
|
|
|
@ -27,11 +27,35 @@
|
|||
#include <pjmedia/types.h>
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup PJMEDIA_WAVE WAVE Header
|
||||
* @ingroup PJMEDIA_MISC
|
||||
* @{
|
||||
*
|
||||
* Supports for simple/canonical Microsoft RIFF WAVE format.
|
||||
*/
|
||||
|
||||
|
||||
PJ_BEGIN_DECL
|
||||
|
||||
/**
|
||||
* Standard RIFF tag to identify RIFF file format in the WAVE header.
|
||||
*/
|
||||
#define PJMEDIA_RIFF_TAG ('F'<<24|'F'<<16|'I'<<8|'R')
|
||||
|
||||
/**
|
||||
* Standard WAVE tag to identify WAVE header.
|
||||
*/
|
||||
#define PJMEDIA_WAVE_TAG ('E'<<24|'V'<<16|'A'<<8|'W')
|
||||
|
||||
/**
|
||||
* Standard FMT tag to identify format chunks.
|
||||
*/
|
||||
#define PJMEDIA_FMT_TAG (' '<<24|'t'<<16|'m'<<8|'f')
|
||||
|
||||
/**
|
||||
* Standard DATA tag to identify data chunks.
|
||||
*/
|
||||
#define PJMEDIA_DATA_TAG ('a'<<24|'t'<<16|'a'<<8|'d')
|
||||
|
||||
|
||||
|
@ -41,26 +65,29 @@ PJ_BEGIN_DECL
|
|||
*/
|
||||
struct pjmedia_wave_hdr
|
||||
{
|
||||
/** This structure describes RIFF WAVE file header */
|
||||
struct {
|
||||
pj_uint32_t riff;
|
||||
pj_uint32_t file_len;
|
||||
pj_uint32_t wave;
|
||||
pj_uint32_t riff; /**< "RIFF" ASCII tag. */
|
||||
pj_uint32_t file_len; /**< File length minus 8 bytes */
|
||||
pj_uint32_t wave; /**< "WAVE" ASCII tag. */
|
||||
} riff_hdr;
|
||||
|
||||
/** This structure describes format chunks/header */
|
||||
struct {
|
||||
pj_uint32_t fmt;
|
||||
pj_uint32_t len;
|
||||
pj_uint16_t fmt_tag;
|
||||
pj_uint16_t nchan;
|
||||
pj_uint32_t sample_rate;
|
||||
pj_uint32_t bytes_per_sec;
|
||||
pj_uint16_t block_align;
|
||||
pj_uint16_t bits_per_sample;
|
||||
pj_uint32_t fmt; /**< "fmt " ASCII tag. */
|
||||
pj_uint32_t len; /**< 16 for PCM. */
|
||||
pj_uint16_t fmt_tag; /**< 1 for PCM */
|
||||
pj_uint16_t nchan; /**< 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. */
|
||||
} fmt_hdr;
|
||||
|
||||
/** The data header preceeds the actual data in the file. */
|
||||
struct {
|
||||
pj_uint32_t data;
|
||||
pj_uint32_t len;
|
||||
pj_uint32_t data; /**< "data" ASCII tag. */
|
||||
pj_uint32_t len; /**< Data length. */
|
||||
} data_hdr;
|
||||
};
|
||||
|
||||
|
@ -98,5 +125,10 @@ PJ_DECL(void) pjmedia_wave_hdr_host_to_file( pjmedia_wave_hdr *hdr );
|
|||
|
||||
PJ_END_DECL
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __PJMEDIA_WAVE_H__ */
|
||||
|
||||
|
|
|
@ -24,84 +24,6 @@
|
|||
#define THIS_FILE "port.c"
|
||||
|
||||
|
||||
/**
|
||||
* Connect two ports.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_port_connect( pj_pool_t *pool,
|
||||
pjmedia_port *upstream_port,
|
||||
pjmedia_port *downstream_port)
|
||||
{
|
||||
pj_status_t status;
|
||||
|
||||
PJ_ASSERT_RETURN(pool && upstream_port && downstream_port, PJ_EINVAL);
|
||||
|
||||
#if 0
|
||||
/* They both MUST have the same media type. */
|
||||
PJ_ASSERT_RETURN(upstream_port->info.type ==
|
||||
downstream_port->info.type, PJMEDIA_ENCTYPE);
|
||||
|
||||
/* They both MUST have the same clock rate. */
|
||||
PJ_ASSERT_RETURN(upstream_port->info.sample_rate ==
|
||||
downstream_port->info.sample_rate, PJMEDIA_ENCCLOCKRATE);
|
||||
|
||||
/* They both MUST have the same samples per frame */
|
||||
PJ_ASSERT_RETURN(upstream_port->info.samples_per_frame ==
|
||||
downstream_port->info.samples_per_frame,
|
||||
PJMEDIA_ENCSAMPLESPFRAME);
|
||||
|
||||
/* They both MUST have the same bits per sample */
|
||||
PJ_ASSERT_RETURN(upstream_port->info.bits_per_sample ==
|
||||
downstream_port->info.bits_per_sample,
|
||||
PJMEDIA_ENCBITS);
|
||||
|
||||
/* They both MUST have the same bytes per frame */
|
||||
PJ_ASSERT_RETURN(upstream_port->info.bytes_per_frame ==
|
||||
downstream_port->info.bytes_per_frame,
|
||||
PJMEDIA_ENCBYTES);
|
||||
#endif
|
||||
|
||||
/* Create mutual attachment. */
|
||||
if (upstream_port->on_downstream_connect) {
|
||||
status = upstream_port->on_downstream_connect( pool, upstream_port,
|
||||
downstream_port );
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (downstream_port->on_upstream_connect) {
|
||||
status = downstream_port->on_upstream_connect( pool, downstream_port,
|
||||
upstream_port );
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Save the attachment. */
|
||||
upstream_port->downstream_port = downstream_port;
|
||||
downstream_port->upstream_port = upstream_port;
|
||||
|
||||
/* Done. */
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect ports.
|
||||
*/
|
||||
PJ_DEF(pj_status_t) pjmedia_port_disconnect( pjmedia_port *upstream_port,
|
||||
pjmedia_port *downstream_port)
|
||||
{
|
||||
PJ_ASSERT_RETURN(upstream_port && downstream_port, PJ_EINVAL);
|
||||
|
||||
if (upstream_port->downstream_port == downstream_port)
|
||||
upstream_port->downstream_port = NULL;
|
||||
|
||||
if (downstream_port->upstream_port == upstream_port)
|
||||
downstream_port->upstream_port = NULL;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a frame from the port (and subsequent downstream ports).
|
||||
*/
|
||||
|
@ -115,7 +37,6 @@ PJ_DEF(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port,
|
|||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Put a frame to the port (and subsequent downstream ports).
|
||||
*/
|
||||
|
@ -139,16 +60,6 @@ PJ_DEF(pj_status_t) pjmedia_port_destroy( pjmedia_port *port )
|
|||
|
||||
PJ_ASSERT_RETURN(port, PJ_EINVAL);
|
||||
|
||||
/* Recursively call this function again to destroy downstream
|
||||
* port first.
|
||||
*/
|
||||
if (port->downstream_port) {
|
||||
status = pjmedia_port_destroy(port->downstream_port);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
pjmedia_port_disconnect(port, port->downstream_port);
|
||||
}
|
||||
|
||||
if (port->on_destroy)
|
||||
status = port->on_destroy(port);
|
||||
else
|
||||
|
@ -159,4 +70,3 @@ PJ_DEF(pj_status_t) pjmedia_port_destroy( pjmedia_port *port )
|
|||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -28,12 +28,12 @@
|
|||
struct resample_port
|
||||
{
|
||||
pjmedia_port base;
|
||||
pjmedia_port *dn_port;
|
||||
unsigned options;
|
||||
pjmedia_resample *resample_get;
|
||||
pjmedia_resample *resample_put;
|
||||
pj_int16_t *get_buf;
|
||||
pj_int16_t *put_buf;
|
||||
unsigned downstream_frame_size;
|
||||
unsigned upstream_frame_size;
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,74 +42,86 @@ static pj_status_t resample_put_frame(pjmedia_port *this_port,
|
|||
const pjmedia_frame *frame);
|
||||
static pj_status_t resample_get_frame(pjmedia_port *this_port,
|
||||
pjmedia_frame *frame);
|
||||
static pj_status_t resample_destroy(pjmedia_port *this_port);
|
||||
|
||||
|
||||
|
||||
PJ_DEF(pj_status_t) pjmedia_resample_port_create( pj_pool_t *pool,
|
||||
pj_bool_t high_quality,
|
||||
pj_bool_t large_filter,
|
||||
unsigned downstream_rate,
|
||||
unsigned upstream_rate,
|
||||
unsigned channel_count,
|
||||
unsigned samples_per_frame,
|
||||
pjmedia_port **p_port )
|
||||
pjmedia_port *dn_port,
|
||||
unsigned clock_rate,
|
||||
unsigned opt,
|
||||
pjmedia_port **p_port )
|
||||
{
|
||||
struct resample_port *rport;
|
||||
unsigned upstream_samples_per_frame;
|
||||
unsigned ptime;
|
||||
pj_status_t status;
|
||||
|
||||
PJ_ASSERT_RETURN(pool && p_port, PJ_EINVAL);
|
||||
/* Validate arguments. */
|
||||
PJ_ASSERT_RETURN(pool && dn_port && clock_rate && p_port, PJ_EINVAL);
|
||||
|
||||
upstream_samples_per_frame = (unsigned)(samples_per_frame * 1.0 *
|
||||
upstream_rate / downstream_rate);
|
||||
/* Only supports 16bit samples per frame */
|
||||
PJ_ASSERT_RETURN(dn_port->info.bits_per_sample == 16, PJMEDIA_ENCBITS);
|
||||
|
||||
ptime = dn_port->info.samples_per_frame * 1000 /
|
||||
dn_port->info.clock_rate;
|
||||
|
||||
/* Create and initialize port. */
|
||||
rport = pj_pool_zalloc(pool, sizeof(struct resample_port));
|
||||
PJ_ASSERT_RETURN(rport != NULL, PJ_ENOMEM);
|
||||
|
||||
rport->base.info.bits_per_sample = 16;
|
||||
rport->base.info.bytes_per_frame = samples_per_frame * BYTES_PER_SAMPLE;
|
||||
rport->base.info.channel_count = channel_count;
|
||||
rport->base.info.clock_rate = clock_rate;
|
||||
rport->base.info.samples_per_frame = clock_rate * ptime / 1000;
|
||||
rport->base.info.bytes_per_frame = rport->base.info.samples_per_frame *
|
||||
BYTES_PER_SAMPLE;
|
||||
rport->base.info.bits_per_sample = BYTES_PER_SAMPLE * 8;
|
||||
rport->base.info.channel_count = dn_port->info.channel_count;
|
||||
rport->base.info.encoding_name = pj_str("pcm");
|
||||
rport->base.info.has_info = 1;
|
||||
rport->base.info.name = pj_str("resample");
|
||||
rport->base.info.need_info = 0;
|
||||
rport->base.info.pt = 0xFF;
|
||||
rport->base.info.clock_rate = upstream_rate;
|
||||
rport->base.info.samples_per_frame = upstream_samples_per_frame;
|
||||
rport->base.info.signature = 0;
|
||||
rport->base.info.signature = PJMEDIA_PORT_SIGNATURE('R','S','M','P');
|
||||
rport->base.info.type = PJMEDIA_TYPE_AUDIO;
|
||||
|
||||
rport->downstream_frame_size = samples_per_frame;
|
||||
rport->upstream_frame_size = upstream_samples_per_frame;
|
||||
rport->dn_port = dn_port;
|
||||
rport->options = opt;
|
||||
|
||||
|
||||
/* Create buffers.
|
||||
* We need separate buffer for get_frame() and put_frame() since
|
||||
* both functions may run simultaneously.
|
||||
*/
|
||||
rport->get_buf = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE);
|
||||
PJ_ASSERT_RETURN(rport->get_buf, PJ_ENOMEM);
|
||||
rport->get_buf = pj_pool_alloc(pool, rport->base.info.bytes_per_frame);
|
||||
PJ_ASSERT_RETURN(rport->get_buf != NULL, PJ_ENOMEM);
|
||||
|
||||
rport->put_buf = pj_pool_alloc(pool, samples_per_frame * BYTES_PER_SAMPLE);
|
||||
PJ_ASSERT_RETURN(rport->put_buf, PJ_ENOMEM);
|
||||
rport->put_buf = pj_pool_alloc(pool, rport->base.info.bytes_per_frame);
|
||||
PJ_ASSERT_RETURN(rport->put_buf != NULL, PJ_ENOMEM);
|
||||
|
||||
|
||||
/* Create "get_frame" resample */
|
||||
status = pjmedia_resample_create( pool, high_quality, large_filter,
|
||||
downstream_rate, upstream_rate,
|
||||
samples_per_frame, &rport->resample_get);
|
||||
status = pjmedia_resample_create(pool,
|
||||
(opt&PJMEDIA_RESAMPLE_USE_LINEAR)==0,
|
||||
(opt&PJMEDIA_RESAMPLE_USE_SMALL_FILTER)==0,
|
||||
dn_port->info.clock_rate,
|
||||
rport->base.info.clock_rate,
|
||||
dn_port->info.samples_per_frame,
|
||||
&rport->resample_get);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
/* Create "put_frame" resample */
|
||||
status = pjmedia_resample_create( pool, high_quality, large_filter,
|
||||
upstream_rate, downstream_rate,
|
||||
upstream_samples_per_frame,
|
||||
&rport->resample_put);
|
||||
status = pjmedia_resample_create(pool,
|
||||
(opt&PJMEDIA_RESAMPLE_USE_LINEAR)==0,
|
||||
(opt&PJMEDIA_RESAMPLE_USE_SMALL_FILTER)==0,
|
||||
rport->base.info.clock_rate,
|
||||
dn_port->info.clock_rate,
|
||||
rport->base.info.samples_per_frame,
|
||||
&rport->resample_put);
|
||||
|
||||
/* Set get_frame and put_frame interface */
|
||||
/* Media port interface */
|
||||
rport->base.get_frame = &resample_get_frame;
|
||||
rport->base.put_frame = &resample_put_frame;
|
||||
rport->base.on_destroy = &resample_destroy;
|
||||
|
||||
|
||||
/* Done */
|
||||
|
@ -127,16 +139,16 @@ static pj_status_t resample_put_frame(pjmedia_port *this_port,
|
|||
pjmedia_frame downstream_frame;
|
||||
|
||||
/* Return if we don't have downstream port. */
|
||||
if (this_port->downstream_port == NULL) {
|
||||
if (rport->dn_port == NULL) {
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
if (frame->type == PJMEDIA_FRAME_TYPE_AUDIO) {
|
||||
pjmedia_resample_run( rport->resample_put, frame->buf, rport->put_buf);
|
||||
pjmedia_resample_run( rport->resample_put, frame->buf,
|
||||
rport->put_buf);
|
||||
|
||||
downstream_frame.buf = rport->put_buf;
|
||||
downstream_frame.size = rport->downstream_frame_size *
|
||||
BYTES_PER_SAMPLE;
|
||||
downstream_frame.size = rport->dn_port->info.bytes_per_frame;
|
||||
} else {
|
||||
downstream_frame.buf = frame->buf;
|
||||
downstream_frame.size = frame->size;
|
||||
|
@ -145,8 +157,7 @@ static pj_status_t resample_put_frame(pjmedia_port *this_port,
|
|||
downstream_frame.type = frame->type;
|
||||
downstream_frame.timestamp.u64 = frame->timestamp.u64;
|
||||
|
||||
return pjmedia_port_put_frame( this_port->downstream_port,
|
||||
&downstream_frame );
|
||||
return pjmedia_port_put_frame( rport->dn_port, &downstream_frame );
|
||||
}
|
||||
|
||||
|
||||
|
@ -155,31 +166,53 @@ static pj_status_t resample_get_frame(pjmedia_port *this_port,
|
|||
pjmedia_frame *frame)
|
||||
{
|
||||
struct resample_port *rport = (struct resample_port*) this_port;
|
||||
pjmedia_frame downstream_frame;
|
||||
pjmedia_frame tmp_frame;
|
||||
pj_status_t status;
|
||||
|
||||
/* Return silence if we don't have downstream port */
|
||||
if (this_port->downstream_port == NULL) {
|
||||
if (rport->dn_port == NULL) {
|
||||
pj_memset(frame->buf, frame->size, 0);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
downstream_frame.buf = rport->get_buf;
|
||||
downstream_frame.size = rport->downstream_frame_size * BYTES_PER_SAMPLE;
|
||||
downstream_frame.timestamp.u64 = frame->timestamp.u64;
|
||||
downstream_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
|
||||
tmp_frame.buf = rport->get_buf;
|
||||
tmp_frame.size = rport->dn_port->info.bytes_per_frame;
|
||||
tmp_frame.timestamp.u64 = frame->timestamp.u64;
|
||||
tmp_frame.type = PJMEDIA_FRAME_TYPE_AUDIO;
|
||||
|
||||
status = pjmedia_port_get_frame( this_port->downstream_port,
|
||||
&downstream_frame);
|
||||
status = pjmedia_port_get_frame( rport->dn_port, &tmp_frame);
|
||||
if (status != PJ_SUCCESS)
|
||||
return status;
|
||||
|
||||
pjmedia_resample_run( rport->resample_get, rport->get_buf, frame->buf);
|
||||
if (tmp_frame.type != PJMEDIA_FRAME_TYPE_AUDIO) {
|
||||
frame->type = tmp_frame.type;
|
||||
frame->timestamp = tmp_frame.timestamp;
|
||||
frame->size = tmp_frame.size;
|
||||
if (tmp_frame.size)
|
||||
pj_memcpy(frame->buf, tmp_frame.buf, tmp_frame.size);
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
frame->size = rport->upstream_frame_size * BYTES_PER_SAMPLE;
|
||||
pjmedia_resample_run( rport->resample_get, tmp_frame.buf, frame->buf);
|
||||
|
||||
frame->size = rport->base.info.bytes_per_frame;
|
||||
frame->type = PJMEDIA_FRAME_TYPE_AUDIO;
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static pj_status_t resample_destroy(pjmedia_port *this_port)
|
||||
{
|
||||
struct resample_port *rport = (struct resample_port*) this_port;
|
||||
|
||||
if ((rport->options & PJMEDIA_RESAMPLE_DONT_DESTROY_DN)==0) {
|
||||
pjmedia_port_destroy(rport->dn_port);
|
||||
rport->dn_port = NULL;
|
||||
}
|
||||
|
||||
/* Nothing else to do */
|
||||
|
||||
return PJ_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,8 @@
|
|||
struct file_port
|
||||
{
|
||||
pjmedia_port base;
|
||||
unsigned options;
|
||||
pj_bool_t eof;
|
||||
pj_size_t bufsize;
|
||||
char *buf;
|
||||
char *readpos;
|
||||
|
@ -114,6 +116,10 @@ static pj_status_t fill_buffer(struct file_port *fport)
|
|||
pj_ssize_t size;
|
||||
pj_status_t status;
|
||||
|
||||
if (fport->eof) {
|
||||
return PJ_EEOF;
|
||||
}
|
||||
|
||||
while (size_left > 0) {
|
||||
|
||||
/* Calculate how many bytes to read in this run. */
|
||||
|
@ -135,11 +141,19 @@ static pj_status_t fill_buffer(struct file_port *fport)
|
|||
* encountered EOF. Rewind the file.
|
||||
*/
|
||||
if (size < (pj_ssize_t)size_to_read) {
|
||||
PJ_LOG(5,(THIS_FILE, "File port %.*s EOF, rewinding..",
|
||||
(int)fport->base.info.name.slen,
|
||||
fport->base.info.name.ptr));
|
||||
fport->fpos = sizeof(struct pjmedia_wave_hdr);
|
||||
pj_file_setpos( fport->fd, fport->fpos, PJ_SEEK_SET);
|
||||
if (fport->options & PJMEDIA_FILE_NO_LOOP) {
|
||||
PJ_LOG(5,(THIS_FILE, "File port %.*s EOF, stopping..",
|
||||
(int)fport->base.info.name.slen,
|
||||
fport->base.info.name.ptr));
|
||||
fport->eof = PJ_TRUE;
|
||||
return PJ_EEOF;
|
||||
} else {
|
||||
PJ_LOG(5,(THIS_FILE, "File port %.*s EOF, rewinding..",
|
||||
(int)fport->base.info.name.slen,
|
||||
fport->base.info.name.ptr));
|
||||
fport->fpos = sizeof(struct pjmedia_wave_hdr);
|
||||
pj_file_setpos( fport->fd, fport->fpos, PJ_SEEK_SET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -156,7 +170,7 @@ static pj_status_t fill_buffer(struct file_port *fport)
|
|||
PJ_DEF(pj_status_t) pjmedia_wav_player_port_create( pj_pool_t *pool,
|
||||
const char *filename,
|
||||
unsigned ptime,
|
||||
unsigned flags,
|
||||
unsigned options,
|
||||
pj_ssize_t buff_size,
|
||||
void *user_data,
|
||||
pjmedia_port **p_port )
|
||||
|
@ -167,8 +181,6 @@ PJ_DEF(pj_status_t) pjmedia_wav_player_port_create( pj_pool_t *pool,
|
|||
pj_status_t status;
|
||||
|
||||
|
||||
PJ_UNUSED_ARG(flags);
|
||||
|
||||
/* Check arguments. */
|
||||
PJ_ASSERT_RETURN(pool && filename && p_port, PJ_EINVAL);
|
||||
|
||||
|
@ -260,6 +272,7 @@ PJ_DEF(pj_status_t) pjmedia_wav_player_port_create( pj_pool_t *pool,
|
|||
|
||||
/* Initialize */
|
||||
fport->base.user_data = user_data;
|
||||
fport->options = options;
|
||||
|
||||
/* Update port info. */
|
||||
fport->base.info.channel_count = wave_hdr.fmt_hdr.nchan;
|
||||
|
@ -337,6 +350,7 @@ PJ_DEF(pj_status_t) pjmedia_wav_player_port_set_pos(pjmedia_port *port,
|
|||
samples * BYTES_PER_SAMPLE;
|
||||
pj_file_setpos( fport->fd, fport->fpos, PJ_SEEK_SET);
|
||||
|
||||
fport->eof = PJ_FALSE;
|
||||
return fill_buffer(fport);
|
||||
}
|
||||
|
||||
|
@ -384,8 +398,11 @@ static pj_status_t file_get_frame(pjmedia_port *this_port,
|
|||
fport->readpos = fport->buf;
|
||||
|
||||
status = fill_buffer(fport);
|
||||
if (status != PJ_SUCCESS)
|
||||
if (status != PJ_SUCCESS) {
|
||||
frame->type = PJMEDIA_FRAME_TYPE_NONE;
|
||||
frame->size = 0;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unsigned endread;
|
||||
|
|
|
@ -127,27 +127,14 @@ int main(int argc, char *argv[])
|
|||
//ptime = samples_per_frame * 1000 / sampling_rate;
|
||||
|
||||
/* Create the resample port. */
|
||||
status = pjmedia_resample_port_create( pool, 1, 1,
|
||||
file_port->info.clock_rate,
|
||||
sampling_rate,
|
||||
channel_count,
|
||||
(unsigned)(
|
||||
samples_per_frame * 1.0 *
|
||||
file_port->info.clock_rate /
|
||||
sampling_rate),
|
||||
status = pjmedia_resample_port_create( pool, file_port,
|
||||
sampling_rate, 0,
|
||||
&resample_port);
|
||||
if (status != PJ_SUCCESS) {
|
||||
app_perror(THIS_FILE, "Unable to create resample port", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Connect resample port to file port */
|
||||
status = pjmedia_port_connect( pool, resample_port, file_port);
|
||||
if (status != PJ_SUCCESS) {
|
||||
app_perror(THIS_FILE, "Error connecting ports", status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Create sound player port. */
|
||||
status = pjmedia_snd_port_create(
|
||||
pool, /* pool */
|
||||
|
|
Loading…
Reference in New Issue