port.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565
  1. /*
  2. * Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
  3. * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18. */
  19. #ifndef __PJMEDIA_PORT_H__
  20. #define __PJMEDIA_PORT_H__
  21. /**
  22. * @file port.h
  23. * @brief Port interface declaration
  24. */
  25. #include <pjmedia/clock.h>
  26. #include <pjmedia/event.h>
  27. #include <pjmedia/format.h>
  28. #include <pjmedia/frame.h>
  29. #include <pjmedia/signatures.h>
  30. #include <pj/assert.h>
  31. #include <pj/lock.h>
  32. #include <pj/os.h>
  33. /**
  34. @addtogroup PJMEDIA_PORT Media Ports Framework
  35. @{
  36. @section media_port_intro Media Port Concepts
  37. @subsection The Media Port
  38. A media port (represented with pjmedia_port "class") provides a generic
  39. and extensible framework for implementing media elements. Media element
  40. itself could be a media source, sink, or processing element. A media
  41. port interface basically has the following properties:
  42. - media port information (pjmedia_port_info) to describe the
  43. media port properties (sampling rate, number of channels, etc.),
  44. - optional pointer to function to acquire frames from the port (the
  45. <tt>get_frame() </tt> interface), which will be called by
  46. #pjmedia_port_get_frame() public API, and
  47. - optional pointer to function to store frames to the port (the
  48. <tt>put_frame()</tt> interface) which will be called by
  49. #pjmedia_port_put_frame() public API.
  50. The <tt>get_frame()</tt> and <tt>put_frame()</tt> interface of course
  51. would only need to be implemented if the media port emits and/or takes
  52. media frames respectively.
  53. Media ports are passive "objects". By default, there is no worker thread
  54. to run the media flow. Applications (or other PJMEDIA
  55. components, as explained in @ref PJMEDIA_PORT_CLOCK) must actively call
  56. #pjmedia_port_get_frame() or #pjmedia_port_put_frame() from/to the media
  57. port in order to retrieve/store media frames.
  58. Some media ports (such as @ref PJMEDIA_CONF and @ref PJMEDIA_RESAMPLE_PORT)
  59. may be interconnected with (or encapsulate) other port, to perform the
  60. combined task of the ports, while some
  61. others represent the ultimate source/sink termination for the media.
  62. Interconnection means the upstream media port will call <tt>get_frame()</tt>
  63. and <tt>put_frame()</tt> to its downstream media port. For this to happen,
  64. the media ports need to have the same format, where format is defined as
  65. combination of sample format, clock rate, channel count, bits per sample,
  66. and samples per frame for audio media.
  67. @subsection port_clock_ex1 Example: Manual Resampling
  68. For example, suppose application wants to convert the sampling rate
  69. of one WAV file to another. In this case, application would create and
  70. arrange media ports connection as follows:
  71. \img{pjmedia/docs/sample-manual-resampling.jpg}
  72. Application would setup the media ports using the following pseudo-
  73. code:
  74. \code
  75. pjmedia_port *player, *resample, *writer;
  76. pj_status_t status;
  77. // Create the file player port.
  78. status = pjmedia_wav_player_port_create(pool,
  79. "Input.WAV", // file name
  80. 20, // ptime.
  81. PJMEDIA_FILE_NO_LOOP, // flags
  82. 0, // buffer size
  83. NULL, // user data.
  84. &player );
  85. PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
  86. // Create the resample port with specifying the target sampling rate,
  87. // and with the file port as the source. This will effectively
  88. // connect the resample port with the player port.
  89. status = pjmedia_resample_port_create( pool, player, 8000,
  90. 0, &resample);
  91. PJ_ASSERT_RETURN(status==PJ_SUCCESS, PJ_SUCCESS);
  92. // Create the file writer, specifying the resample port's configuration
  93. // as the WAV parameters.
  94. status pjmedia_wav_writer_port_create(pool,
  95. "Output.WAV", // file name.
  96. resample->info.clock_rate,
  97. resample->info.channel_count,
  98. resample->info.samples_per_frame,
  99. resample->info.bits_per_sample,
  100. 0, // flags
  101. 0, // buffer size
  102. NULL, // user data.
  103. &writer);
  104. \endcode
  105. After the ports have been set up, application can perform the conversion
  106. process by running this loop:
  107. \code
  108. pj_int16_t samplebuf[MAX_FRAME];
  109. while (1) {
  110. pjmedia_frame frame;
  111. pj_status_t status;
  112. frame.buf = samplebuf;
  113. frame.size = sizeof(samplebuf);
  114. // Get the frame from resample port.
  115. status = pjmedia_port_get_frame(resample, &frame);
  116. if (status != PJ_SUCCESS || frame.type == PJMEDIA_FRAME_TYPE_NONE) {
  117. // End-of-file, end the conversion.
  118. break;
  119. }
  120. // Put the frame to write port.
  121. status = pjmedia_port_put_frame(writer, &frame);
  122. if (status != PJ_SUCCESS) {
  123. // Error in writing the file.
  124. break;
  125. }
  126. }
  127. \endcode
  128. For the sake of completeness, after the resampling process is done,
  129. application would need to destroy the ports:
  130. \code
  131. // Note: by default, destroying resample port will destroy the
  132. // the downstream port too.
  133. pjmedia_port_destroy(resample);
  134. pjmedia_port_destroy(writer);
  135. \endcode
  136. The above steps are okay for our simple purpose of changing file's sampling
  137. rate. But for other purposes, the process of reading and writing frames
  138. need to be done in timely manner (for example, sending RTP packets to
  139. remote stream). And more over, as the application's scope goes bigger,
  140. the same pattern of manually reading/writing frames comes up more and more often,
  141. thus perhaps it would be better if PJMEDIA provides mechanism to
  142. automate this process.
  143. And indeed PJMEDIA does provide such mechanism, which is described in
  144. @ref PJMEDIA_PORT_CLOCK section.
  145. @subsection media_port_autom Automating Media Flow
  146. PJMEDIA provides few mechanisms to make media flows automatically
  147. among media ports. This concept is described in @ref PJMEDIA_PORT_CLOCK
  148. section.
  149. */
  150. PJ_BEGIN_DECL
  151. /* Since media port's callback is called synchronously and has a return value,
  152. * it can introduce a deadlock when a mutex is held before calling it.
  153. * To prevent this, media ports' set_eof_cb() and set_cb() functions have
  154. * been deprecated and replaced by set_eof_cb2() and set_cb2(), which
  155. * will call the callback asynchronously without expecting any return value.
  156. *
  157. * See also https://github.com/pjsip/pjproject/issues/2251.
  158. */
  159. #ifndef DEPRECATED_FOR_TICKET_2251
  160. # define DEPRECATED_FOR_TICKET_2251 0
  161. #endif
  162. /**
  163. * Create 32bit port signature from ASCII characters.
  164. */
  165. #define PJMEDIA_PORT_SIG(a,b,c,d) PJMEDIA_OBJ_SIG(a,b,c,d)
  166. /**
  167. * Port operation setting.
  168. */
  169. typedef enum pjmedia_port_op
  170. {
  171. /**
  172. * No change to the port TX or RX settings.
  173. */
  174. PJMEDIA_PORT_NO_CHANGE,
  175. /**
  176. * TX or RX is disabled from the port. It means get_frame() or
  177. * put_frame() WILL NOT be called for this port.
  178. */
  179. PJMEDIA_PORT_DISABLE,
  180. /**
  181. * TX or RX is muted, which means that get_frame() or put_frame()
  182. * will still be called, but the audio frame is discarded.
  183. */
  184. PJMEDIA_PORT_MUTE,
  185. /**
  186. * Enable TX and RX to/from this port.
  187. */
  188. PJMEDIA_PORT_ENABLE
  189. } pjmedia_port_op;
  190. /**
  191. * Port info.
  192. */
  193. typedef struct pjmedia_port_info
  194. {
  195. pj_str_t name; /**< Port name. */
  196. pj_uint32_t signature; /**< Port signature. */
  197. pjmedia_dir dir; /**< Port direction. */
  198. pjmedia_format fmt; /**< Format. */
  199. } pjmedia_port_info;
  200. /**
  201. * Utility to retrieve audio clock rate/sampling rate value from
  202. * pjmedia_port_info.
  203. *
  204. * @param pia Pointer to port info containing audio format.
  205. * @return Audio clock rate.
  206. */
  207. PJ_INLINE(unsigned) PJMEDIA_PIA_SRATE(const pjmedia_port_info *pia)
  208. {
  209. pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
  210. pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
  211. return pia->fmt.det.aud.clock_rate;
  212. }
  213. /**
  214. * Utility to retrieve audio channel count value from pjmedia_port_info.
  215. *
  216. * @param pia Pointer to port info containing audio format.
  217. * @return Audio channel count.
  218. */
  219. PJ_INLINE(unsigned) PJMEDIA_PIA_CCNT(const pjmedia_port_info *pia)
  220. {
  221. pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
  222. pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
  223. return pia->fmt.det.aud.channel_count;
  224. }
  225. /**
  226. * Utility to retrieve audio bits per sample value from pjmedia_port_info.
  227. *
  228. * @param pia Pointer to port info containing audio format.
  229. * @return Number of bits per sample.
  230. */
  231. PJ_INLINE(unsigned) PJMEDIA_PIA_BITS(const pjmedia_port_info *pia)
  232. {
  233. pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
  234. pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
  235. return pia->fmt.det.aud.bits_per_sample;
  236. }
  237. /**
  238. * Utility to retrieve audio frame interval (ptime) value from
  239. * pjmedia_port_info.
  240. *
  241. * @param pia Pointer to port info containing audio format.
  242. * @return Frame interval in msec.
  243. */
  244. PJ_INLINE(unsigned) PJMEDIA_PIA_PTIME(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.frame_time_usec / 1000;
  249. }
  250. /**
  251. * This is a utility routine to retrieve the audio samples_per_frame value
  252. * from port info.
  253. *
  254. * @param pia Pointer to port info containing audio format.
  255. * @return Samples per frame value.
  256. */
  257. PJ_INLINE(unsigned) PJMEDIA_PIA_SPF(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 PJMEDIA_AFD_SPF(&pia->fmt.det.aud);
  262. }
  263. /**
  264. * This is a utility routine to retrieve the average bitrate value
  265. * from port info.
  266. *
  267. * @param pia Pointer to port info containing audio format.
  268. * @return Bitrate, in bits per second.
  269. */
  270. PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_BPS(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.avg_bps;
  275. }
  276. /**
  277. * This is a utility routine to retrieve the maximum bitrate value
  278. * from port info.
  279. *
  280. * @param pia Pointer to port info containing audio format.
  281. * @return Bitrate, in bits per second.
  282. */
  283. PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_BPS(const pjmedia_port_info *pia)
  284. {
  285. pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
  286. pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
  287. return pia->fmt.det.aud.max_bps;
  288. }
  289. /**
  290. * This is a utility routine to retrieve the average audio frame size value
  291. * from pjmedia_port_info.
  292. *
  293. * @param pia Pointer to port info containing audio format.
  294. * @return Frame size in bytes.
  295. */
  296. PJ_INLINE(unsigned) PJMEDIA_PIA_AVG_FSZ(const pjmedia_port_info *pia)
  297. {
  298. pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
  299. pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
  300. return PJMEDIA_AFD_AVG_FSZ(&pia->fmt.det.aud);
  301. }
  302. /**
  303. * Utility to retrieve audio frame size from maximum bitrate from
  304. * pjmedia_port_info.
  305. *
  306. * @param pia Pointer to port info containing audio format.
  307. * @return Frame size in bytes.
  308. */
  309. PJ_INLINE(unsigned) PJMEDIA_PIA_MAX_FSZ(const pjmedia_port_info *pia)
  310. {
  311. pj_assert(pia->fmt.type==PJMEDIA_TYPE_AUDIO &&
  312. pia->fmt.detail_type==PJMEDIA_FORMAT_DETAIL_AUDIO);
  313. return PJMEDIA_AFD_MAX_FSZ(&pia->fmt.det.aud);
  314. }
  315. /**
  316. * Port interface.
  317. */
  318. typedef struct pjmedia_port
  319. {
  320. pjmedia_port_info info; /**< Port information. */
  321. /** Port data can be used by the port creator to attach arbitrary
  322. * value to be associated with the port.
  323. */
  324. struct port_data {
  325. void *pdata; /**< Pointer data. */
  326. long ldata; /**< Long data. */
  327. } port_data;
  328. /**
  329. * Group lock.
  330. *
  331. * This is optional, but if this port is registered to the audio/video
  332. * conference bridge, the bridge will create one if the port has none.
  333. */
  334. pj_grp_lock_t *grp_lock;
  335. /**
  336. * Get clock source.
  337. * This should only be called by #pjmedia_port_get_clock_src().
  338. */
  339. pjmedia_clock_src* (*get_clock_src)(struct pjmedia_port *this_port,
  340. pjmedia_dir dir);
  341. /**
  342. * Sink interface.
  343. * This should only be called by #pjmedia_port_put_frame().
  344. */
  345. pj_status_t (*put_frame)(struct pjmedia_port *this_port,
  346. pjmedia_frame *frame);
  347. /**
  348. * Source interface.
  349. * This should only be called by #pjmedia_port_get_frame().
  350. */
  351. pj_status_t (*get_frame)(struct pjmedia_port *this_port,
  352. pjmedia_frame *frame);
  353. /**
  354. * Called to destroy this port.
  355. */
  356. pj_status_t (*on_destroy)(struct pjmedia_port *this_port);
  357. } pjmedia_port;
  358. /**
  359. * This is an auxiliary function to initialize port info for
  360. * ports which deal with PCM audio.
  361. *
  362. * @param info The port info to be initialized.
  363. * @param name Port name.
  364. * @param signature Port signature.
  365. * @param clock_rate Port's clock rate.
  366. * @param channel_count Number of channels.
  367. * @param bits_per_sample Bits per sample.
  368. * @param samples_per_frame Number of samples per frame.
  369. *
  370. * @return PJ_SUCCESS on success.
  371. */
  372. PJ_DECL(pj_status_t) pjmedia_port_info_init( pjmedia_port_info *info,
  373. const pj_str_t *name,
  374. unsigned signature,
  375. unsigned clock_rate,
  376. unsigned channel_count,
  377. unsigned bits_per_sample,
  378. unsigned samples_per_frame);
  379. /**
  380. * This is an auxiliary function to initialize port info for
  381. * ports which deal with PCM audio.
  382. *
  383. * @param info The port info to be initialized.
  384. * @param name Port name.
  385. * @param signature Port signature.
  386. * @param dir Port's direction.
  387. * @param fmt Port's media format.
  388. *
  389. * @return PJ_SUCCESS on success.
  390. */
  391. PJ_DECL(pj_status_t) pjmedia_port_info_init2(pjmedia_port_info *info,
  392. const pj_str_t *name,
  393. unsigned signature,
  394. pjmedia_dir dir,
  395. const pjmedia_format *fmt);
  396. /**
  397. * Get a clock source from the port.
  398. *
  399. * @param port The media port.
  400. * @param dir Media port's direction.
  401. *
  402. * @return The clock source or NULL if clock source is not present
  403. * in the port.
  404. */
  405. PJ_DECL(pjmedia_clock_src *) pjmedia_port_get_clock_src( pjmedia_port *port,
  406. pjmedia_dir dir );
  407. /**
  408. * Get a frame from the port (and subsequent downstream ports).
  409. *
  410. * @param port The media port.
  411. * @param frame Frame to store samples.
  412. *
  413. * @return PJ_SUCCESS on success, or the appropriate error code.
  414. */
  415. PJ_DECL(pj_status_t) pjmedia_port_get_frame( pjmedia_port *port,
  416. pjmedia_frame *frame );
  417. /**
  418. * Put a frame to the port (and subsequent downstream ports).
  419. *
  420. * @param port The media port.
  421. * @param frame Frame to the put to the port.
  422. *
  423. * @return PJ_SUCCESS on success, or the appropriate error code.
  424. */
  425. PJ_DECL(pj_status_t) pjmedia_port_put_frame( pjmedia_port *port,
  426. pjmedia_frame *frame );
  427. /**
  428. * Destroy port (and subsequent downstream ports).
  429. *
  430. * Note that if the port has group lock, instead of destroying the port
  431. * immediately, this function will just decrease the reference counter.
  432. *
  433. * @param port The media port.
  434. *
  435. * @return PJ_SUCCESS on success, or the appropriate error code.
  436. */
  437. PJ_DECL(pj_status_t) pjmedia_port_destroy( pjmedia_port *port );
  438. /**
  439. * This is a helper function to initialize the port's group lock. This
  440. * function will create a group lock if NULL is passed, initialize the group
  441. * lock by adding the port's destructor to the group lock handler list, and
  442. * increment the reference counter.
  443. *
  444. * This function should only be called by a media port implementation and
  445. * after port's on_destroy() function has been assigned.
  446. *
  447. * @param port The pjmedia port to be initialized.
  448. * @param pool The pool, this can be a temporary pool as
  449. * group lock will create and use its internal pool.
  450. * @param glock The group lock, or create a new one if NULL.
  451. *
  452. * @return PJ_SUCCESS on success, PJ_EEXISTS if group lock
  453. * is already initialized, or the other appropriate
  454. * error code.
  455. */
  456. PJ_DECL(pj_status_t) pjmedia_port_init_grp_lock( pjmedia_port *port,
  457. pj_pool_t *pool,
  458. pj_grp_lock_t *glock );
  459. /**
  460. * This is a helper function to increase the port reference counter.
  461. *
  462. * @param port The PJMEDIA port.
  463. *
  464. * @return PJ_SUCCESS on success.
  465. */
  466. PJ_DECL(pj_status_t) pjmedia_port_add_ref( pjmedia_port *port );
  467. /**
  468. * This is a helper function to decrease the port reference counter.
  469. *
  470. * @param port The PJMEDIA port.
  471. *
  472. * @return PJ_SUCCESS on success.
  473. */
  474. PJ_DECL(pj_status_t) pjmedia_port_dec_ref( pjmedia_port *port );
  475. PJ_END_DECL
  476. /**
  477. * @}
  478. */
  479. #endif /* __PJMEDIA_PORT_H__ */