/usr/include/sipxtapi/mp/MprDelay.h is in libsipxtapi-dev 3.3.0~test17-2.1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 | //
// Copyright (C) 2008 SIPfoundry Inc.
// Licensed by SIPfoundry under the LGPL license.
//
// Copyright (C) 2008 SIPez LLC.
// Licensed to SIPfoundry under a Contributor Agreement.
//
// $$
//////////////////////////////////////////////////////////////////////////////
// Author: Sergey Kostanbaev <Sergey DOT Kostanbaev AT sipez DOT com>
#ifndef _MprDelay_h_
#define _MprDelay_h_
// SYSTEM INCLUDES
// APPLICATION INCLUDES
#include "mp/MpAudioResource.h"
#include "mp/MpAudioBuf.h"
#include "mp/MpResourceMsg.h"
// DEFINES
// MACROS
// EXTERNAL FUNCTIONS
// EXTERNAL VARIABLES
// STRUCTS
// TYPEDEFS
// FORWARD DECLARATIONS
/**
* @brief Delay Resource
*
* This resource is intended to add user-controlled delay to audio stream.
* Such a strange feature may be useful in many advanced use-cases, e.g. when
* our network may be not ready to accept data at the moment data becomes
* ready.
*
* <h3> Internal state machine description </h3>
*
* Delay resource can be found in four internal states:
* 1) WAITING. This is initial state of resource after creation and also is
* the state after stopPlay() call. WAITING state means that resource is idle
* and do not appear to have active audio input. No frames are produced on
* output.
*
* WAITING state will be changed to BUFFERING automatically when frame with
* active audio is received, and it can be manually changed to PLAYING state
* by calling startPlay() method.
*
* <pre> active voice
* WAITING ---------------> BUFFERING
* |
* | startPlay()
* v
* PLAYING
* </pre>
*
* <pre> stopPlay()
* WAITING <--------------- BUFFERING
* ^ ^______________________
* | stopPlay() |
* | stopPlay() |
* PLAYING PLAYING_WITHOUT_DELAY
* </pre>
*
* 2) BUFFERING. In this state resource stores all incoming frames to internal
* circular buffer and does not produce any output. Thus the longer resource
* remains in this state, the longer delay will be introduced.
*
* This state can only be reached from WAITING state in case active voice has
* been received. Calling startPlay() in BUFFERING state leads to transition
* to PLAYING state, calling stopPlay() moves resource back to WAITING state.
*
*
* <pre> active voice
* WAITING ---------------> BUFFERING
* ^______________________| |
* stopPlay() |
* __________________________|
* | startPlay()
* v
* PLAYING
* </pre>
*
* 3) PLAYING. In this state resource pops recorded data from the head of
* internal buffer and sends it to output, adding newly arrived data to
* the tail of internal buffer. I.e. data is played back with constant delay,
* which depends on the time spent in BUFFERING state.
*
* Resource can be put to PLAYING state only manually by calling startPlay()
* method. Calling stopPlay() method when in PLAYING state will move resource
* to WAITING state. If internal buffer is empty then resource will
* automatically fall through to PLAYING_WITHOUT_DELAY state.
*
* 4) PLAYING_WITHOUT_DELAY. In this case every input frame is directly
* forwarded to the output, i.e. no delay is introduced. At this moment
* this state is hardly useful, but it is thought to become useful when
* delay resource is able to "catch up", i.e. reduce delay to zero using
* e.g. timescaling technique. From application perspective this state
* is indistinguishable from PLAYING state.
*
* This state can only be reached from PLAYING state if internal buffer
* is empty. Calling stopPlay() will move resource to WAITING state.
*
* <pre> stopPlay()
* WAITING <------------------------.
* |
* |
* empty buffer |
* PLAYING --------------> PLAYING_WITHOUT_DELAY
* </pre>
*
*
* <h3> Notifications </h3>
*
* 1) When state changes from WAITING to BUFFERING (i.e. when active audio is
* detected on input) resource emits MPRNM_DELAY_SPEECH_STARTED notification.
* User should respond to this notification by calling startPlay() when
* he thinks relevant. User can also call stopPlay() to put resource into
* WAITING state again. Until one of this action is performed resource
* will buffer input data and thus increase induced delay.
*
* 2) When resource in PLAYING state detects, that its buffer contain only
* NULL frames and frames with inactive audio it emits MPRNM_DELAY_QUIESCENCE
* for user to perform any relevant actions. E.g. user can call stopPlay()
* and power down network interface, if there are no other active audio
* sources. Note, that at in current implementation MPRNM_DELAY_QUIESCENCE
* notification is not emited in PLAYING_WITHOUT_DELAY state.
*
* 3) When resource detects active audio after quescent situation have been
* recently detected resource emits MPRNM_DELAY_SPEECH_STARTED notification.
* This should warn user that resource's buffer contain active audio again.
*
* 4) When resource in PLAYING state detects empty internal buffer it emits
* MPRNM_DELAY_NO_DELAY notification and enters PLAYING_WITHOUT_DELAY state.
*
* <h3> How to control Delay resource </h3>
*
* If you're using flowgraph with Delay resources in it you must control them
* with care. Use case deemed to be most useful consists of three steps repeated
* foreveris as outlined below:
*
* 1) Initially Delay resource is in WAITING state. User is listenning for
* notifications and honestly expects MPRNM_DELAY_SPEECH_STARTED to appear
* soon.
* 2) MPRNM_DELAY_SPEECH_STARTED is received by user which means that resource
* is now in BUFFERING state. It will remain in this state until user calls
* either startPlay() or stopPlay(). Once user thinks it's the time to start
* playback (e.g. network interface have woken) he calls startPlay()
* (goto (3) then) and resource is put into PLAYING state. If for any reason
* user thinks buffered audio should be discarded he calls stopPlay() to put
* resource to WAITING state again (goto (1) then).
* 3) In PLAYING state user can call stopPlay() at any time to discard buffered
* frames and put resource into WAITING state (goto (1) then). But it's most
* reasonable to wait for MPRNM_DELAY_QUIESCENCE notification and call
* stopPlay() only them. This will minimize impact on audio quality caused
* by dropped frames.
*
* @nosubgrouping
*/
class MprDelay : public MpAudioResource
{
/* //////////////////////////////// PUBLIC //////////////////////////////// */
public:
enum
{
DEFAULT_FIFO_CAPACITY = 1000
};
/* =============================== CREATORS =============================== */
///@name Creators
//@{
/// Constructor
MprDelay(const UtlString& rName, int capacity = DEFAULT_FIFO_CAPACITY);
/// Destructor
~MprDelay();
//@}
/* ============================= MANIPULATORS ============================= */
///@name Manipulators
//@{
/// Send message to start play
static UtlBoolean startPlay(const UtlString& namedResource,
OsMsgQ& fgQ);
/// Send message to stop play
static UtlBoolean stopPlay(const UtlString& namedResource,
OsMsgQ& fgQ);
//@}
/* ============================== ACCESSORS =============================== */
///@name Accessors
//@{
//@}
/* =============================== INQUIRY ================================ */
///@name Inquiry
//@{
/// Get delay in milliseconds.
int getDelayMs();
/// Get delay in samples.
int getDelaySamples();
/// Get delay in frames.
int getDelayFrames();
//@}
/* ////////////////////////////// PROTECTED /////////////////////////////// */
protected:
UtlBoolean doDelay(MpBufPtr& inBuf,
MpBufPtr& outBuf,
int samplesPerFrame,
int samplesPerSecond);
/// @copydoc MpResource::handleMessage
UtlBoolean handleMessage(MpResourceMsg& rMsg);
/// @copydoc MpAudioResource::doProcessFrame
UtlBoolean doProcessFrame(MpBufPtr inBufs[],
MpBufPtr outBufs[],
int inBufsSize,
int outBufsSize,
UtlBoolean isEnabled,
int samplesPerFrame,
int samplesPerSecond);
/* /////////////////////////////// PRIVATE //////////////////////////////// */
private:
enum MprDelayState
{
MPDS_WAITING,
MPDS_BUFFERING,
MPDS_PLAYING,
MPDS_PLAYING_WITHOUT_DELAY
};
typedef enum
{
MPRM_DELAY_START_PLAY = MpResourceMsg::MPRM_EXTERNAL_MESSAGE_START,
MPRM_DELAY_STOP_PLAY
} AddlMsgTypes;
/**
* @brief Fifo for Delay resource
*
* @nosubgrouping
*/
class MprDelayFifo
{
/* ///////////////////////////// PUBLIC //////////////////////////////// */
public:
/* ============================ CREATORS =============================== */
///@name Creators
//@{
/// Constructor
MprDelayFifo(int capacity);
/// Destructor
~MprDelayFifo();
//@}
/* ========================== MANIPULATORS ============================= */
///@name Manipulators
//@{
/// Reset FIFO
void reset();
/// Push audio buffer to FIFO
void pushData(MpAudioBufPtr& databuff);
/// Pop audio buffer from FIFO
void popData(MpAudioBufPtr& databuff);
/**<
* User must ensure that queue is not empty by himself.
* Pop from an empty queue will corrupt its internal state.
*/
//@}
/* =========================== ACCESSORS =============================== */
///@name Accessors
//@{
/// Get number of buffers in queue
int getFifoLength() const;
//@}
/* ============================ INQUIRY ================================ */
///@name Inquiry
//@{
/// Does FIFO contain only silent frames?
UtlBoolean isQuiescent() const;
/// Is FIFIO empty
UtlBoolean isEmpty() const;
//@}
/* /////////////////////////// PROTECTED /////////////////////////////// */
protected:
/* //////////////////////////// PRIVATE //////////////////////////////// */
private:
MpAudioBufPtr* mBuff;
int mBuffSize;
int mEndPosition;
int mStartPosition;
int mNumActiveFrames;
};
MprDelayState mState; ///< State of delay resource
UtlBoolean mIsQuiescenceNotified; ///< Have FIFO quiescent state been notified?
MprDelayFifo mFifo; ///< FIFO for the stored data
};
/* ============================ INLINE METHODS ============================ */
#endif // _MprDelay_h_
|