blob: 4ea5de1d571fe385b091258516f99a08b9e1078c [file] [log] [blame]
Tristan Matthews0a329cc2013-07-17 13:20:14 -04001/* $Id$ */
2/*
3 * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
5 *
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.
10 *
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.
15 *
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
19 */
20#ifndef __PJMEDIA_PORT_H__
21#define __PJMEDIA_PORT_H__
22
23/**
24 * @file port.h
25 * @brief Port interface declaration
26 */
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>
33#include <pj/os.h>
34
35
36/**
37 @addtogroup PJMEDIA_PORT Media Ports Framework
38 @{
39
40 @section media_port_intro Media Port Concepts
41
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.
55
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.
59
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.
65
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.
75
76
77 @subsection port_clock_ex1 Example: Manual Resampling
78
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:
82
83 \image html sample-manual-resampling.jpg
84
85 Application would setup the media ports using the following pseudo-
86 code:
87
88 \code
89
90 pjmedia_port *player, *resample, *writer;
91 pj_status_t status;
92
93 // Create the file player port.
94 status = pjmedia_wav_player_port_create(pool,
95 "Input.WAV", // file name
96 20, // ptime.
97 PJMEDIA_FILE_NO_LOOP, // flags
98 0, // buffer size
99 NULL, // user data.
100 &player );
101 PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
102
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,
107 0, &resample);
108 PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
109
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,
118 0, // flags
119 0, // buffer size
120 NULL, // user data.
121 &writer);
122
123 \endcode
124
125
126 After the ports have been set up, application can perform the conversion
127 process by running this loop:
128
129 \code
130
131 pj_int16_t samplebuf[MAX_FRAME];
132
133 while (1) {
134 pjmedia_frame frame;
135 pj_status_t status;
136
137 frame.buf = samplebuf;
138 frame.size = sizeof(samplebuf);
139
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.
144 break;
145 }
146
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.
151 break;
152 }
153 }
154
155 \endcode
156
157 For the sake of completeness, after the resampling process is done,
158 application would need to destroy the ports:
159
160 \code
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);
165 \endcode
166
167
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.
175
176 And indeed PJMEDIA does provide such mechanism, which is described in
177 @ref PJMEDIA_PORT_CLOCK section.
178
179
180 @subsection media_port_autom Automating Media Flow
181
182 PJMEDIA provides few mechanisms to make media flows automatically
183 among media ports. This concept is described in @ref PJMEDIA_PORT_CLOCK
184 section.
185*/
186
187PJ_BEGIN_DECL
188
189
190/**
191 * Create 32bit port signature from ASCII characters.
192 */
193#define PJMEDIA_PORT_SIG(a,b,c,d) PJMEDIA_OBJ_SIG(a,b,c,d)
194
195
196/**
197 * Port operation setting.
198 */
199typedef enum pjmedia_port_op
200{
201 /**
202 * No change to the port TX or RX settings.
203 */
204 PJMEDIA_PORT_NO_CHANGE,
205
206 /**
207 * TX or RX is disabled from the port. It means get_frame() or
208 * put_frame() WILL NOT be called for this port.
209 */
210 PJMEDIA_PORT_DISABLE,
211
212 /**
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.
215 */
216 PJMEDIA_PORT_MUTE,
217
218 /**
219 * Enable TX and RX to/from this port.
220 */
221 PJMEDIA_PORT_ENABLE
222
223} pjmedia_port_op;
224
225
226/**
227 * Port info.
228 */
229typedef struct pjmedia_port_info
230{
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. */
235} pjmedia_port_info;
236
237/**
238 * Utility to retrieve audio clock rate/sampling rate value from
239 * pjmedia_port_info.
240 *
241 * @param pia Pointer to port info containing audio format.
242 * @return Audio clock rate.
243 */
244PJ_INLINE(unsigned) PJMEDIA_PIA_SRATE(const pjmedia_port_info *pia)
245{
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;
249}
250
251/**
252 * Utility to retrieve audio channel count value from pjmedia_port_info.
253 *
254 * @param pia Pointer to port info containing audio format.
255 * @return Audio channel count.
256 */
257PJ_INLINE(unsigned) PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia)
258{
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;
262}
263
264/**
265 * Utility to retrieve audio bits per sample value from pjmedia_port_info.
266 *
267 * @param pia Pointer to port info containing audio format.
268 * @return Number of bits per sample.
269 */
270PJ_INLINE(unsigned) PJMEDIA_PIA_BITS(const pjmedia_port_info *pia)
271{
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;
275}
276
277/**
278 * Utility to retrieve audio frame interval (ptime) value from
279 * pjmedia_port_info.
280 *
281 * @param pia Pointer to port info containing audio format.
282 * @return Frame interval in msec.
283 */
284PJ_INLINE(unsigned) PJMEDIA_PIA_PTIME(const pjmedia_port_info *pia)
285{
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;
289}
290
291/**
292 * This is a utility routine to retrieve the audio samples_per_frame value
293 * from port info.
294 *
295 * @param pia Pointer to port info containing audio format.
296 * @return Samples per frame value.
297 */
298PJ_INLINE(unsigned) PJMEDIA_PIA_SPF(const pjmedia_port_info *pia)
299{
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);
303}
304
305/**
306 * This is a utility routine to retrieve the average bitrate value
307 * from port info.
308 *
309 * @param pia Pointer to port info containing audio format.
310 * @return Bitrate, in bits per second.
311 */
312PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_BPS(const pjmedia_port_info *pia)
313{
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;
317}
318
319/**
320 * This is a utility routine to retrieve the maximum bitrate value
321 * from port info.
322 *
323 * @param pia Pointer to port info containing audio format.
324 * @return Bitrate, in bits per second.
325 */
326PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_BPS(const pjmedia_port_info *pia)
327{
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;
331}
332
333/**
334 * This is a utility routine to retrieve the average audio frame size value
335 * from pjmedia_port_info.
336 *
337 * @param pia Pointer to port info containing audio format.
338 * @return Frame size in bytes.
339 */
340PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_FSZ(const pjmedia_port_info *pia)
341{
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);
345}
346
347/**
348 * Utility to retrieve audio frame size from maximum bitrate from
349 * pjmedia_port_info.
350 *
351 * @param pia Pointer to port info containing audio format.
352 * @return Frame size in bytes.
353 */
354PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_FSZ(const pjmedia_port_info *pia)
355{
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);
359}
360
361/**
362 * Port interface.
363 */
364typedef struct pjmedia_port
365{
366 pjmedia_port_info info; /**< Port information. */
367
368 /** Port data can be used by the port creator to attach arbitrary
369 * value to be associated with the port.
370 */
371 struct port_data {
372 void *pdata; /**< Pointer data. */
373 long ldata; /**< Long data. */
374 } port_data;
375
376 /**
377 * Get clock source.
378 * This should only be called by #pjmedia_port_get_clock_src().
379 */
380 pjmedia_clock_src* (*get_clock_src)(struct pjmedia_port *this_port,
381 pjmedia_dir dir);
382
383 /**
384 * Sink interface.
385 * This should only be called by #pjmedia_port_put_frame().
386 */
387 pj_status_t (*put_frame)(struct pjmedia_port *this_port,
388 pjmedia_frame *frame);
389
390 /**
391 * Source interface.
392 * This should only be called by #pjmedia_port_get_frame().
393 */
394 pj_status_t (*get_frame)(struct pjmedia_port *this_port,
395 pjmedia_frame *frame);
396
397 /**
398 * Called to destroy this port.
399 */
400 pj_status_t (*on_destroy)(struct pjmedia_port *this_port);
401
402} pjmedia_port;
403
404
405/**
406 * This is an auxiliary function to initialize port info for
407 * ports which deal with PCM audio.
408 *
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.
416 *
417 * @return PJ_SUCCESS on success.
418 */
419PJ_DECL(pj_status_t) pjmedia_port_info_init( pjmedia_port_info *info,
420 const pj_str_t *name,
421 unsigned signature,
422 unsigned clock_rate,
423 unsigned channel_count,
424 unsigned bits_per_sample,
425 unsigned samples_per_frame);
426
427/**
428 * This is an auxiliary function to initialize port info for
429 * ports which deal with PCM audio.
430 *
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.
436 *
437 * @return PJ_SUCCESS on success.
438 */
439PJ_DECL(pj_status_t) pjmedia_port_info_init2(pjmedia_port_info *info,
440 const pj_str_t *name,
441 unsigned signature,
442 pjmedia_dir dir,
443 const pjmedia_format *fmt);
444
445
446/**
447 * Get a clock source from the port.
448 *
449 * @param port The media port.
450 * @param dir Media port's direction.
451 *
452 * @return The clock source or NULL if clock source is not present
453 * in the port.
454 */
455PJ_DECL(pjmedia_clock_src *) pjmedia_port_get_clock_src( pjmedia_port *port,
456 pjmedia_dir dir );
457
458
459/**
460 * Get a frame from the port (and subsequent downstream ports).
461 *
462 * @param port The media port.
463 * @param frame Frame to store samples.
464 *
465 * @return PJ_SUCCESS on success, or the appropriate error code.
466 */
467PJ_DECL(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port,
468 pjmedia_frame *frame );
469
470/**
471 * Put a frame to the port (and subsequent downstream ports).
472 *
473 * @param port The media port.
474 * @param frame Frame to the put to the port.
475 *
476 * @return PJ_SUCCESS on success, or the appropriate error code.
477 */
478PJ_DECL(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port,
479 pjmedia_frame *frame );
480
481/**
482 * Destroy port (and subsequent downstream ports)
483 *
484 * @param port The media port.
485 *
486 * @return PJ_SUCCESS on success, or the appropriate error code.
487 */
488PJ_DECL(pj_status_t) pjmedia_port_destroy( pjmedia_port *port );
489
490
491
492PJ_END_DECL
493
494/**
495 * @}
496 */
497
498#endif /* __PJMEDIA_PORT_H__ */
499