1
/* $Id: port.h 3893 2011-12-01 10:49:07Z ming $ */
3
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20
#ifndef __PJMEDIA_PORT_H__
21
#define __PJMEDIA_PORT_H__
25
* @brief Port interface declaration
27
#include <pjmedia/clock.h>
28
#include <pjmedia/event.h>
29
#include <pjmedia/format.h>
30
#include <pjmedia/frame.h>
31
#include <pjmedia/signatures.h>
32
#include <pj/assert.h>
37
@addtogroup PJMEDIA_PORT Media Ports Framework
40
@section media_port_intro Media Port Concepts
42
@subsection The Media Port
43
A media port (represented with pjmedia_port "class") provides a generic
44
and extensible framework for implementing media elements. Media element
45
itself could be a media source, sink, or processing element. A media
46
port interface basically has the following properties:
47
- media port information (pjmedia_port_info) to describe the
48
media port properties (sampling rate, number of channels, etc.),
49
- optional pointer to function to acquire frames from the port (the
50
<tt>get_frame() </tt> interface), which will be called by
51
#pjmedia_port_get_frame() public API, and
52
- optional pointer to function to store frames to the port (the
53
<tt>put_frame()</tt> interface) which will be called by
54
#pjmedia_port_put_frame() public API.
56
The <tt>get_frame()</tt> and <tt>put_frame()</tt> interface of course
57
would only need to be implemented if the media port emits and/or takes
58
media frames respectively.
60
Media ports are passive "objects". By default, there is no worker thread
61
to run the media flow. Applications (or other PJMEDIA
62
components, as explained in @ref PJMEDIA_PORT_CLOCK) must actively call
63
#pjmedia_port_get_frame() or #pjmedia_port_put_frame() from/to the media
64
port in order to retrieve/store media frames.
66
Some media ports (such as @ref PJMEDIA_CONF and @ref PJMEDIA_RESAMPLE_PORT)
67
may be interconnected with (or encapsulate) other port, to perform the
68
combined task of the ports, while some
69
others represent the ultimate source/sink termination for the media.
70
Interconnection means the upstream media port will call <tt>get_frame()</tt>
71
and <tt>put_frame()</tt> to its downstream media port. For this to happen,
72
the media ports need to have the same format, where format is defined as
73
combination of sample format, clock rate, channel count, bits per sample,
74
and samples per frame for audio media.
77
@subsection port_clock_ex1 Example: Manual Resampling
79
For example, suppose application wants to convert the sampling rate
80
of one WAV file to another. In this case, application would create and
81
arrange media ports connection as follows:
83
\image html sample-manual-resampling.jpg
85
Application would setup the media ports using the following pseudo-
90
pjmedia_port *player, *resample, *writer;
93
// Create the file player port.
94
status = pjmedia_wav_player_port_create(pool,
95
"Input.WAV", // file name
97
PJMEDIA_FILE_NO_LOOP, // flags
101
PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
103
// Create the resample port with specifying the target sampling rate,
104
// and with the file port as the source. This will effectively
105
// connect the resample port with the player port.
106
status = pjmedia_resample_port_create( pool, player, 8000,
108
PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
110
// Create the file writer, specifying the resample port's configuration
111
// as the WAV parameters.
112
status pjmedia_wav_writer_port_create(pool,
113
"Output.WAV", // file name.
114
resample->info.clock_rate,
115
resample->info.channel_count,
116
resample->info.samples_per_frame,
117
resample->info.bits_per_sample,
126
After the ports have been set up, application can perform the conversion
127
process by running this loop:
131
pj_int16_t samplebuf[MAX_FRAME];
137
frame.buf = samplebuf;
138
frame.size = sizeof(samplebuf);
140
// Get the frame from resample port.
141
status = pjmedia_port_get_frame(resample, &frame);
142
if (status != PJ_SUCCESS || frame.type == PJMEDIA_FRAME_TYPE_NONE) {
143
// End-of-file, end the conversion.
147
// Put the frame to write port.
148
status = pjmedia_port_put_frame(writer, &frame);
149
if (status != PJ_SUCCESS) {
150
// Error in writing the file.
157
For the sake of completeness, after the resampling process is done,
158
application would need to destroy the ports:
161
// Note: by default, destroying resample port will destroy the
162
// the downstream port too.
163
pjmedia_port_destroy(resample);
164
pjmedia_port_destroy(writer);
168
The above steps are okay for our simple purpose of changing file's sampling
169
rate. But for other purposes, the process of reading and writing frames
170
need to be done in timely manner (for example, sending RTP packets to
171
remote stream). And more over, as the application's scope goes bigger,
172
the same pattern of manually reading/writing frames comes up more and more often,
173
thus perhaps it would be better if PJMEDIA provides mechanism to
174
automate this process.
176
And indeed PJMEDIA does provide such mechanism, which is described in
177
@ref PJMEDIA_PORT_CLOCK section.
180
@subsection media_port_autom Automating Media Flow
182
PJMEDIA provides few mechanisms to make media flows automatically
183
among media ports. This concept is described in @ref PJMEDIA_PORT_CLOCK
191
* Create 32bit port signature from ASCII characters.
193
#define PJMEDIA_PORT_SIG(a,b,c,d) PJMEDIA_OBJ_SIG(a,b,c,d)
197
* Port operation setting.
199
typedef enum pjmedia_port_op
202
* No change to the port TX or RX settings.
204
PJMEDIA_PORT_NO_CHANGE,
207
* TX or RX is disabled from the port. It means get_frame() or
208
* put_frame() WILL NOT be called for this port.
210
PJMEDIA_PORT_DISABLE,
213
* TX or RX is muted, which means that get_frame() or put_frame()
214
* will still be called, but the audio frame is discarded.
219
* Enable TX and RX to/from this port.
229
typedef struct pjmedia_port_info
231
pj_str_t name; /**< Port name. */
232
pj_uint32_t signature; /**< Port signature. */
233
pjmedia_dir dir; /**< Port direction. */
234
pjmedia_format fmt; /**< Format. */
238
* Utility to retrieve audio clock rate/sampling rate value from
241
* @param pia Pointer to port info containing audio format.
242
* @return Audio clock rate.
244
PJ_INLINE(unsigned) PJMEDIA_PIA_SRATE(const pjmedia_port_info *pia)
246
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
247
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
248
return pia->fmt.det.aud.clock_rate;
252
* Utility to retrieve audio channel count value from pjmedia_port_info.
254
* @param pia Pointer to port info containing audio format.
255
* @return Audio channel count.
257
PJ_INLINE(unsigned) PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia)
259
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
260
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
261
return pia->fmt.det.aud.channel_count;
265
* Utility to retrieve audio bits per sample value from pjmedia_port_info.
267
* @param pia Pointer to port info containing audio format.
268
* @return Number of bits per sample.
270
PJ_INLINE(unsigned) PJMEDIA_PIA_BITS(const pjmedia_port_info *pia)
272
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
273
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
274
return pia->fmt.det.aud.bits_per_sample;
278
* Utility to retrieve audio frame interval (ptime) value from
281
* @param pia Pointer to port info containing audio format.
282
* @return Frame interval in msec.
284
PJ_INLINE(unsigned) PJMEDIA_PIA_PTIME(const pjmedia_port_info *pia)
286
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
287
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
288
return pia->fmt.det.aud.frame_time_usec / 1000;
292
* This is a utility routine to retrieve the audio samples_per_frame value
295
* @param pia Pointer to port info containing audio format.
296
* @return Samples per frame value.
298
PJ_INLINE(unsigned) PJMEDIA_PIA_SPF(const pjmedia_port_info *pia)
300
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
301
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
302
return PJMEDIA_AFD_SPF(&pia->fmt.det.aud);
306
* This is a utility routine to retrieve the average bitrate value
309
* @param pia Pointer to port info containing audio format.
310
* @return Bitrate, in bits per second.
312
PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_BPS(const pjmedia_port_info *pia)
314
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
315
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
316
return pia->fmt.det.aud.avg_bps;
320
* This is a utility routine to retrieve the maximum bitrate value
323
* @param pia Pointer to port info containing audio format.
324
* @return Bitrate, in bits per second.
326
PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_BPS(const pjmedia_port_info *pia)
328
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
329
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
330
return pia->fmt.det.aud.max_bps;
334
* This is a utility routine to retrieve the average audio frame size value
335
* from pjmedia_port_info.
337
* @param pia Pointer to port info containing audio format.
338
* @return Frame size in bytes.
340
PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_FSZ(const pjmedia_port_info *pia)
342
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
343
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
344
return PJMEDIA_AFD_AVG_FSZ(&pia->fmt.det.aud);
348
* Utility to retrieve audio frame size from maximum bitrate from
351
* @param pia Pointer to port info containing audio format.
352
* @return Frame size in bytes.
354
PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_FSZ(const pjmedia_port_info *pia)
356
pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
357
pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
358
return PJMEDIA_AFD_MAX_FSZ(&pia->fmt.det.aud);
364
typedef struct pjmedia_port
366
pjmedia_port_info info; /**< Port information. */
368
/** Port data can be used by the port creator to attach arbitrary
369
* value to be associated with the port.
372
void *pdata; /**< Pointer data. */
373
long ldata; /**< Long data. */
378
* This should only be called by #pjmedia_port_get_clock_src().
380
pjmedia_clock_src* (*get_clock_src)(struct pjmedia_port *this_port,
385
* This should only be called by #pjmedia_port_put_frame().
387
pj_status_t (*put_frame)(struct pjmedia_port *this_port,
388
pjmedia_frame *frame);
392
* This should only be called by #pjmedia_port_get_frame().
394
pj_status_t (*get_frame)(struct pjmedia_port *this_port,
395
pjmedia_frame *frame);
398
* Called to destroy this port.
400
pj_status_t (*on_destroy)(struct pjmedia_port *this_port);
406
* This is an auxiliary function to initialize port info for
407
* ports which deal with PCM audio.
409
* @param info The port info to be initialized.
410
* @param name Port name.
411
* @param signature Port signature.
412
* @param clock_rate Port's clock rate.
413
* @param channel_count Number of channels.
414
* @param bits_per_sample Bits per sample.
415
* @param samples_per_frame Number of samples per frame.
417
* @return PJ_SUCCESS on success.
419
PJ_DECL(pj_status_t) pjmedia_port_info_init( pjmedia_port_info *info,
420
const pj_str_t *name,
423
unsigned channel_count,
424
unsigned bits_per_sample,
425
unsigned samples_per_frame);
428
* This is an auxiliary function to initialize port info for
429
* ports which deal with PCM audio.
431
* @param info The port info to be initialized.
432
* @param name Port name.
433
* @param signature Port signature.
434
* @param dir Port's direction.
435
* @param fmt Port's media format.
437
* @return PJ_SUCCESS on success.
439
PJ_DECL(pj_status_t) pjmedia_port_info_init2(pjmedia_port_info *info,
440
const pj_str_t *name,
443
const pjmedia_format *fmt);
447
* Get a clock source from the port.
449
* @param port The media port.
450
* @param dir Media port's direction.
452
* @return The clock source or NULL if clock source is not present
455
PJ_DECL(pjmedia_clock_src *) pjmedia_port_get_clock_src( pjmedia_port *port,
460
* Get a frame from the port (and subsequent downstream ports).
462
* @param port The media port.
463
* @param frame Frame to store samples.
465
* @return PJ_SUCCESS on success, or the appropriate error code.
467
PJ_DECL(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port,
468
pjmedia_frame *frame );
471
* Put a frame to the port (and subsequent downstream ports).
473
* @param port The media port.
474
* @param frame Frame to the put to the port.
476
* @return PJ_SUCCESS on success, or the appropriate error code.
478
PJ_DECL(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port,
479
pjmedia_frame *frame );
482
* Destroy port (and subsequent downstream ports)
484
* @param port The media port.
486
* @return PJ_SUCCESS on success, or the appropriate error code.
488
PJ_DECL(pj_status_t) pjmedia_port_destroy( pjmedia_port *port );
498
#endif /* __PJMEDIA_PORT_H__ */