1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef ANDROID_AUDIO_FIFO_H 18 #define ANDROID_AUDIO_FIFO_H 19 20 #include <stdlib.h> 21 #include <audio_utils/fifo_index.h> 22 23 #ifndef __cplusplus 24 #error C API is no longer supported 25 #endif 26 27 /** Indicates whether index is multi-thread safe, and the synchronization technique. */ 28 enum audio_utils_fifo_sync { 29 /** Index is not multi-thread safe. No support for synchronization or timeouts. */ 30 AUDIO_UTILS_FIFO_SYNC_SINGLE_THREADED, 31 /** Index is multi-thread safe. Synchronization is by polling, timeouts by clock_nanosleep(). */ 32 AUDIO_UTILS_FIFO_SYNC_SLEEP, 33 /** Index is multi-thread safe. Synchronization is by futex mapped in one process. */ 34 AUDIO_UTILS_FIFO_SYNC_PRIVATE, 35 /** Index is multi-thread safe. Synchronization is by futex mapped in one or more processes. */ 36 AUDIO_UTILS_FIFO_SYNC_SHARED, 37 }; 38 39 /** 40 * Base class for single-writer, single-reader or multi-reader, optionally blocking FIFO. 41 * The base class manipulates frame indices only, and has no knowledge of frame sizes or the buffer. 42 * At most one reader, called the "throttling reader", can block the writer. 43 * The "fill level", or unread frame count, is defined with respect to the throttling reader. 44 */ 45 class audio_utils_fifo_base { 46 47 public: 48 49 /** 50 * Return the capacity, or statically configured maximum frame count. 51 * 52 * \return The capacity in frames. 53 */ capacity()54 uint32_t capacity() const 55 { return mFrameCount; } 56 57 protected: 58 59 /** 60 * Construct FIFO base class 61 * 62 * \param frameCount Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX, 63 * aka "capacity". 64 * If release()s always use the same count, and the count is a divisor of 65 * (effective) \p frameCount, then the obtain()s won't ever be fragmented. 66 * \param writerRear Writer's rear index. Passed by reference because it must be non-NULL. 67 * \param throttleFront Pointer to the front index of at most one reader that throttles the 68 * writer, or NULL for no throttling. 69 * \param sync Index synchronization, defaults to AUDIO_UTILS_FIFO_SYNC_SHARED but can 70 * also be any other value. 71 */ 72 audio_utils_fifo_base(uint32_t frameCount, audio_utils_fifo_index& writerRear, 73 audio_utils_fifo_index *throttleFront = NULL, 74 audio_utils_fifo_sync sync = AUDIO_UTILS_FIFO_SYNC_SHARED); 75 /*virtual*/ ~audio_utils_fifo_base(); 76 77 /** Return a new index as the sum of a validated index and a specified increment. 78 * 79 * \param index Caller should supply a validated mFront or mRear. 80 * \param increment Value to be added to the index <= mFrameCount. 81 * 82 * \return The sum of index plus increment. 83 */ 84 uint32_t sum(uint32_t index, uint32_t increment) const; 85 86 /** Return the difference between two indices: rear - front. 87 * 88 * \param rear Caller should supply an unvalidated mRear. 89 * \param front Caller should supply an unvalidated mFront. 90 * \param lost If non-NULL, set to the approximate number of frames lost before 91 * re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost. 92 * \param flush Whether to flush the entire buffer on -EOVERFLOW. 93 * 94 * \return The zero or positive difference <= mFrameCount, or a negative error code. 95 * \retval -EIO corrupted indices, no recovery is possible 96 * \retval -EOVERFLOW reader doesn't throttle writer, and frames were lost because reader 97 * isn't keeping up with writer; see \p lost 98 */ 99 int32_t diff(uint32_t rear, uint32_t front, size_t *lost = NULL, bool flush = false) const; 100 101 /** 102 * Mark the FIFO as shutdown (permanently unusable), usually due to an -EIO status from an API. 103 * Thereafter, all APIs that return a status will return -EIO, and other APIs will be no-ops. 104 */ 105 void shutdown() const; 106 107 // These fields are const after initialization 108 109 /** Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX, aka "capacity". */ 110 const uint32_t mFrameCount; 111 /** Equal to roundup(mFrameCount). */ 112 const uint32_t mFrameCountP2; 113 114 /** 115 * Equal to mFrameCountP2 - mFrameCount, the number of "wasted" frames after the end of mBuffer. 116 * Only the indices are wasted, not any memory. 117 */ 118 const uint32_t mFudgeFactor; 119 120 /** Reference to writer's rear index. */ 121 audio_utils_fifo_index& mWriterRear; 122 /** Indicates how synchronization is done for mWriterRear. */ 123 const audio_utils_fifo_sync mWriterRearSync; 124 125 /** 126 * Pointer to the front index of at most one reader that throttles the writer, 127 * or NULL for no throttling. 128 */ 129 audio_utils_fifo_index* const mThrottleFront; 130 /** Indicates how synchronization is done for mThrottleFront. */ 131 const audio_utils_fifo_sync mThrottleFrontSync; 132 133 /** Whether FIFO is marked as shutdown due to detection of an "impossible" error condition. */ 134 mutable bool mIsShutdown; 135 }; 136 137 //////////////////////////////////////////////////////////////////////////////// 138 139 /** 140 * Same as audio_utils_fifo_base, but understands frame sizes and knows about the buffer but does 141 * not own it. 142 */ 143 class audio_utils_fifo : public audio_utils_fifo_base { 144 145 friend class audio_utils_fifo_reader; 146 friend class audio_utils_fifo_writer; 147 template <typename T> friend class audio_utils_fifo_writer_T; 148 149 public: 150 151 /** 152 * Construct a FIFO object: multi-process. 153 * Index synchronization is not configurable; it is always AUDIO_UTILS_FIFO_SYNC_SHARED. 154 * 155 * \param frameCount Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX, 156 * aka "capacity". 157 * If writes and reads always use the same count, and the count is a divisor 158 * of \p frameCount, then the writes and reads won't do a partial transfer. 159 * \param frameSize Size of each frame in bytes > 0, 160 * \p frameSize * \p frameCount <= INT32_MAX. 161 * \param buffer Pointer to a non-NULL caller-allocated buffer of \p frameCount frames. 162 * \param writerRear Writer's rear index. Passed by reference because it must be non-NULL. 163 * \param throttleFront Pointer to the front index of at most one reader that throttles the 164 * writer, or NULL for no throttling. 165 */ 166 audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer, 167 audio_utils_fifo_index& writerRear, audio_utils_fifo_index *throttleFront = NULL); 168 169 /** 170 * Construct a FIFO object: single-process. 171 * \param frameCount Maximum usable frames to be stored in the FIFO > 0 && <= INT32_MAX, 172 * aka "capacity". 173 * If writes and reads always use the same count, and the count is a divisor 174 * of \p frameCount, then the writes and reads won't do a partial transfer. 175 * \param frameSize Size of each frame in bytes > 0, 176 * \p frameSize * \p frameCount <= INT32_MAX. 177 * \param buffer Pointer to a non-NULL caller-allocated buffer of \p frameCount frames. 178 * \param throttlesWriter Whether there is one reader that throttles the writer. 179 * \param sync Index synchronization, defaults to AUDIO_UTILS_FIFO_SYNC_PRIVATE but can 180 * also be AUDIO_UTILS_FIFO_SYNC_SINGLE_THREADED or AUDIO_UTILS_FIFO_SYNC_SLEEP. 181 * AUDIO_UTILS_FIFO_SYNC_SHARED is not permitted. 182 */ 183 audio_utils_fifo(uint32_t frameCount, uint32_t frameSize, void *buffer, 184 bool throttlesWriter = true, 185 audio_utils_fifo_sync sync = AUDIO_UTILS_FIFO_SYNC_PRIVATE); 186 187 /*virtual*/ ~audio_utils_fifo(); 188 189 /** 190 * Return the frame size in bytes. 191 * 192 * \return frame size in bytes, always > 0. 193 */ frameSize()194 uint32_t frameSize() const 195 { return mFrameSize; } 196 197 /** 198 * Return a pointer to the caller-allocated buffer. 199 * 200 * \return non-NULL pointer to buffer. 201 */ buffer()202 void *buffer() const 203 { return mBuffer; } 204 205 private: 206 // These fields are const after initialization 207 const uint32_t mFrameSize; // size of each frame in bytes 208 void * const mBuffer; // non-NULL pointer to caller-allocated buffer 209 // of size mFrameCount frames 210 211 // only used for single-process constructor 212 audio_utils_fifo_index mSingleProcessSharedRear; 213 214 // only used for single-process constructor when throttlesWriter == true 215 audio_utils_fifo_index mSingleProcessSharedFront; 216 }; 217 218 /** 219 * Describes one virtually contiguous fragment of a logically contiguous slice. 220 * Compare to struct iovec for readv(2) and writev(2). 221 */ 222 struct audio_utils_iovec { 223 /** Offset of fragment in frames, relative to mBuffer, undefined if mLength == 0 */ 224 uint32_t mOffset; 225 /** Length of fragment in frames, 0 means fragment is empty */ 226 uint32_t mLength; 227 }; 228 229 //////////////////////////////////////////////////////////////////////////////// 230 231 /** 232 * Based on frameworks/av/include/media/AudioBufferProvider.h 233 */ 234 class audio_utils_fifo_provider { 235 public: 236 audio_utils_fifo_provider(audio_utils_fifo& fifo); 237 virtual ~audio_utils_fifo_provider(); 238 239 /** 240 * Obtain access to a logically contiguous slice of a stream, represented by \p iovec. 241 * For the reader(s), the slice is initialized and has read-only access. 242 * For the writer, the slice is uninitialized and has read/write access. 243 * It is permitted to call obtain() multiple times without an intervening release(). 244 * Each call resets the notion of most recently obtained slice. 245 * 246 * \param iovec Non-NULL pointer to a pair of fragment descriptors. 247 * On entry, the descriptors may be uninitialized. 248 * On exit, the descriptors are initialized and refer to each of the two fragments. 249 * iovec[0] describes the initial fragment of the slice, and 250 * iovec[1] describes the remaining non-virtually-contiguous fragment. 251 * Empty iovec[0] implies that iovec[1] is also empty. 252 * iovec[0].mOffset and iovec[1].mOffset are always < capacity. 253 * Typically iovec[1].mOffset is zero, but don't assume that. 254 * \param count The maximum number of frames to obtain. 255 * See setHysteresis() for something which is close to, but not the same as, 256 * a minimum. 257 * \param timeout Indicates the maximum time to block for at least one frame. 258 * NULL and {0, 0} both mean non-blocking. 259 * Time is expressed as relative CLOCK_MONOTONIC. 260 * As an optimization, if \p timeout->tv_sec is the maximum positive value for 261 * time_t (LONG_MAX), then the implementation treats it as infinite timeout. 262 * See fifo_index.h for explanation of why representation is struct timespec. 263 * 264 * \return Actual number of frames available, if greater than or equal to zero. 265 * Guaranteed to be <= \p count and == iovec[0].mLength + iovec[1].mLength. 266 * For a reader this is also guaranteed to be <= capacity. 267 * For a writer this is also guaranteed to be <= effective buffer size, 268 * even if there is no reader that throttles writer. 269 * 270 * \retval -EIO corrupted indices, no recovery is possible 271 * \retval -EOVERFLOW reader doesn't throttle writer, and frames were lost because reader 272 * isn't keeping up with writer; see \p lost 273 * \retval -ETIMEDOUT count is greater than zero, timeout is non-NULL and not {0, 0}, 274 * timeout expired, and no frames were available after the timeout. 275 * \retval -EINTR count is greater than zero, timeout is non-NULL and not {0, 0}, timeout 276 * was interrupted by a signal, and no frames were available after signal. 277 * \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0}, 278 * futex wait failed due to benign race, and unable to converge after 279 * retrying. Should usually handle like -EINTR. 280 * 281 * Applications should treat all of these as equivalent to zero available frames, 282 * except they convey extra information as to the cause. 283 * After any error, both iovec[0] and iovec[1] will be empty. 284 */ 285 virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count = SIZE_MAX, 286 const struct timespec *timeout = NULL) = 0; 287 288 /** 289 * Release access to a portion of the most recently obtained slice. 290 * It is permitted to call release() multiple times without an intervening obtain(). 291 * 292 * \param count Number of frames to release. The cumulative number of frames released must not 293 * exceed the number of frames most recently obtained. 294 * If it ever happens, then the FIFO will be marked unusable with shutdown(). 295 */ 296 virtual void release(size_t count) = 0; 297 298 /** 299 * Determine the number of frames that could be obtained or read/written without blocking. 300 * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted. 301 * available() may be called after obtain(), but doesn't affect the number of releasable frames. 302 * The implementation unfortunately prevents the method from being marked 'const'. 303 * 304 * \return Number of available frames, if greater than or equal to zero. 305 * \retval -EIO corrupted indices, no recovery is possible 306 * \retval -EOVERFLOW reader doesn't throttle writer, and frames were lost because reader 307 * isn't keeping up with writer 308 */ 309 virtual ssize_t available() = 0; 310 311 /** 312 * Return the capacity, or statically configured maximum frame count. 313 * 314 * \return The capacity in frames. 315 */ capacity()316 uint32_t capacity() const 317 { return mFifo.capacity(); } 318 319 /** 320 * Return the total number of frames released since construction. 321 * For a reader, this includes lost and flushed frames. 322 * 323 * \return Total frames released. 324 */ totalReleased()325 uint64_t totalReleased() const 326 { return mTotalReleased; } 327 328 /** Return a reference to the associated FIFO. */ fifo()329 audio_utils_fifo& fifo() { return mFifo; } 330 331 protected: 332 audio_utils_fifo& mFifo; 333 334 /** Number of frames obtained at most recent obtain(), less total number of frames released. */ 335 uint32_t mObtained; 336 337 /** Number of times to retry a futex wait that fails with EWOULDBLOCK. */ 338 static const int kRetries = 2; 339 340 /** 341 * Total number of frames released since construction. 342 * For a reader, this includes lost and flushed frames. 343 */ 344 uint64_t mTotalReleased; 345 }; 346 347 //////////////////////////////////////////////////////////////////////////////// 348 349 /** 350 * Used to write to a FIFO. There should be exactly one writer per FIFO. 351 * The writer is multi-thread safe with respect to reader(s), 352 * but not with respect to multiple threads calling the writer API. 353 */ 354 class audio_utils_fifo_writer : public audio_utils_fifo_provider { 355 356 public: 357 /** 358 * Single-process and multi-process use same constructor here, 359 * but different FIFO constructors. 360 * 361 * \param fifo Associated FIFO. Passed by reference because it must be non-NULL. 362 */ 363 explicit audio_utils_fifo_writer(audio_utils_fifo& fifo); 364 virtual ~audio_utils_fifo_writer(); 365 366 /** 367 * Write to FIFO. Resets the number of releasable frames to zero. 368 * 369 * \param buffer Pointer to source buffer containing \p count frames of data. 370 * Pointer must be non-NULL if \p count is greater than zero. 371 * \param count Desired number of frames to write. 372 * \param timeout Indicates the maximum time to block for at least one frame. 373 * NULL and {0, 0} both mean non-blocking. 374 * Time is expressed as relative CLOCK_MONOTONIC. 375 * As an optimization, if \p timeout->tv_sec is the maximum positive value for 376 * time_t (LONG_MAX), then the implementation treats it as infinite timeout. 377 * See fifo_index.h for explanation of why representation is struct timespec. 378 * 379 * \return Actual number of frames written, if greater than or equal to zero. 380 * Guaranteed to be <= \p count. 381 * Also guaranteed to be <= effective buffer size, 382 * even if there is no reader that throttles writer. 383 * The actual transfer count may be zero if the FIFO is full, 384 * or partial if the FIFO was almost full. 385 * \retval -EIO corrupted indices, no recovery is possible 386 * \retval -ETIMEDOUT count is greater than zero, timeout is non-NULL and not {0, 0}, 387 * timeout expired, and no frames were available after the timeout. 388 * \retval -EINTR count is greater than zero, timeout is non-NULL and not {0, 0}, timeout 389 * was interrupted by a signal, and no frames were available after signal. 390 * \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0}, 391 * futex wait failed due to benign race, and unable to converge after 392 * retrying. Should usually handle like -EINTR. 393 */ 394 ssize_t write(const void *buffer, size_t count, const struct timespec *timeout = NULL); 395 396 // Implement audio_utils_fifo_provider 397 virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count = SIZE_MAX, 398 const struct timespec *timeout = NULL); 399 virtual void release(size_t count); 400 virtual ssize_t available(); 401 402 /** 403 * Set the current effective buffer size. 404 * Any filled frames already written or released to the buffer are unaltered, and pending 405 * releasable frames from obtain() may be release()ed. However subsequent write() and obtain() 406 * will be limited such that the total filled frame count is <= the effective buffer size. 407 * The default effective buffer size is mFifo.mFrameCount. 408 * Reducing the effective buffer size may update the hysteresis levels; see getHysteresis(). 409 * 410 * \param frameCount effective buffer size in frames. Capped to range [0, mFifo.mFrameCount]. 411 */ 412 void resize(uint32_t frameCount); 413 414 /** 415 * Get the current effective buffer size. 416 * This value is not exposed to reader(s), and so must be conveyed via an out-of-band channel. 417 * 418 * \return effective buffer size in frames 419 */ 420 uint32_t size() const; 421 422 /** 423 * Set the hysteresis levels for the writer to wake blocked readers. 424 * Hysteresis can decrease the number of context switches between writer and a blocking reader. 425 * A non-empty write() or release() will wake readers 426 * only if the fill level was < \p armLevel before the write() or release(), 427 * and then the fill level became > \p triggerLevel afterwards. 428 * The default value for \p armLevel is mFifo.mFrameCount, which means always armed. 429 * The default value for \p triggerLevel is zero, 430 * which means every write() or release() will wake the readers. 431 * For hysteresis, \p armLevel must be <= \p triggerLevel + 1. 432 * Increasing \p armLevel will arm for wakeup, regardless of the current fill level. 433 * 434 * \param armLevel Arm for wakeup when fill level < this value. 435 * Capped to range [0, effective buffer size]. 436 * \param triggerLevel Trigger wakeup when armed and fill level > this value. 437 * Capped to range [0, effective buffer size]. 438 */ 439 void setHysteresis(uint32_t armLevel, uint32_t triggerLevel); 440 441 /** 442 * Get the hysteresis levels for waking readers. 443 * 444 * \param armLevel Set to the current arm level in frames. 445 * \param triggerLevel Set to the current trigger level in frames. 446 */ 447 void getHysteresis(uint32_t *armLevel, uint32_t *triggerLevel) const; 448 449 private: 450 // Accessed by writer only using ordinary operations 451 uint32_t mLocalRear; // frame index of next frame slot available to write, or write index 452 453 // TODO make a separate class and associate with the synchronization object 454 uint32_t mArmLevel; // arm if filled < arm level before release() 455 uint32_t mTriggerLevel; // trigger if armed and filled > trigger level after release() 456 bool mIsArmed; // whether currently armed 457 458 uint32_t mEffectiveFrames; // current effective buffer size, <= mFifo.mFrameCount 459 }; 460 461 //////////////////////////////////////////////////////////////////////////////// 462 463 /** 464 * Used to read from a FIFO. There can be one or more readers per FIFO, 465 * and at most one of those readers can throttle the writer. 466 * All other readers must keep up with the writer or they will lose frames. 467 * Each reader is multi-thread safe with respect to the writer and any other readers, 468 * but not with respect to multiple threads calling the reader API. 469 */ 470 class audio_utils_fifo_reader : public audio_utils_fifo_provider { 471 472 public: 473 /** 474 * Single-process and multi-process use same constructor here, 475 * but different FIFO constructors. 476 * 477 * \param fifo Associated FIFO. Passed by reference because it must be non-NULL. 478 * \param throttlesWriter Whether this reader throttles the writer. 479 * At most one reader can specify throttlesWriter == true. 480 * A non-throttling reader does not see any data written 481 * prior to construction of the reader. 482 * \param flush Whether to flush (discard) the entire buffer on -EOVERFLOW. 483 * The advantage of flushing is that it increases the chance that next 484 * read will be successful. The disadvantage is that it loses more data. 485 */ 486 explicit audio_utils_fifo_reader(audio_utils_fifo& fifo, bool throttlesWriter = true, 487 bool flush = false); 488 virtual ~audio_utils_fifo_reader(); 489 490 /** 491 * Read from FIFO. Resets the number of releasable frames to zero. 492 * 493 * \param buffer Pointer to destination buffer to be filled with up to \p count frames of data. 494 * Pointer must be non-NULL if \p count is greater than zero. 495 * \param count Desired number of frames to read. 496 * \param timeout Indicates the maximum time to block for at least one frame. 497 * NULL and {0, 0} both mean non-blocking. 498 * Time is expressed as relative CLOCK_MONOTONIC. 499 * As an optimization, if \p timeout->tv_sec is the maximum positive value for 500 * time_t (LONG_MAX), then the implementation treats it as infinite timeout. 501 * See fifo_index.h for explanation of why representation is struct timespec. 502 * \param lost If non-NULL, set to the approximate number of frames lost before 503 * re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost. 504 * 505 * \return Actual number of frames read, if greater than or equal to zero. 506 * Guaranteed to be <= \p count. 507 * Also guaranteed to be <= capacity. 508 * The actual transfer count may be zero if the FIFO is empty, 509 * or partial if the FIFO was almost empty. 510 * \retval -EIO corrupted indices, no recovery is possible 511 * \retval -EOVERFLOW reader doesn't throttle writer, and frames were lost because reader 512 * isn't keeping up with writer; see \p lost 513 * \retval -ETIMEDOUT count is greater than zero, timeout is non-NULL and not {0, 0}, 514 * timeout expired, and no frames were available after the timeout. 515 * \retval -EINTR count is greater than zero, timeout is non-NULL and not {0, 0}, timeout 516 * was interrupted by a signal, and no frames were available after signal. 517 * \retval -EWOULDBLOCK count is greater than zero, timeout is non-NULL and not {0, 0}, 518 * futex wait failed due to benign race, and unable to converge after 519 * retrying. Should usually handle like -EINTR. 520 */ 521 ssize_t read(void *buffer, size_t count, const struct timespec *timeout = NULL, 522 size_t *lost = NULL); 523 524 // Implement audio_utils_fifo_provider 525 virtual ssize_t obtain(audio_utils_iovec iovec[2], size_t count = SIZE_MAX, 526 const struct timespec *timeout = NULL); 527 virtual void release(size_t count); 528 virtual ssize_t available(); 529 530 /** 531 * Same as audio_utils_fifo_provider::obtain, except has an additional parameter \p lost. 532 * 533 * \param iovec See audio_utils_fifo_provider::obtain. 534 * \param count See audio_utils_fifo_provider::obtain. 535 * \param timeout See audio_utils_fifo_provider::obtain. 536 * \param lost If non-NULL, set to the approximate number of frames lost before 537 * re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost. 538 * \return See audio_utils_fifo_provider::obtain for 'Returns' and 'Return values'. 539 */ 540 ssize_t obtain(audio_utils_iovec iovec[2], size_t count, const struct timespec *timeout, 541 size_t *lost); 542 543 /** 544 * Determine the number of frames that could be obtained or read without blocking. 545 * There's an inherent race condition: the value may soon be obsolete so shouldn't be trusted. 546 * available() may be called after obtain(), but doesn't affect the number of releasable frames. 547 * The implementation unfortunately prevents the method from being marked 'const'. 548 * 549 * \param lost If non-NULL, set to the approximate number of frames lost before 550 * re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost. 551 * 552 * \return Number of available frames, if greater than or equal to zero. 553 * \retval -EIO corrupted indices, no recovery is possible 554 * \retval -EOVERFLOW reader doesn't throttle writer, and frames were lost because reader 555 * isn't keeping up with writer; see \p lost 556 */ 557 ssize_t available(size_t *lost); 558 559 /** 560 * Flush (discard) all frames that could be obtained or read without blocking. 561 * Note that flush is a method on a reader, so if the writer wants to flush 562 * then it must communicate the request to the reader(s) via an out-of-band channel. 563 * 564 * \param lost If non-NULL, set to the approximate number of frames lost before 565 * re-synchronization when -EOVERFLOW occurs, or set to zero when no frames lost. 566 * 567 * \return Number of flushed frames, if greater than or equal to zero. 568 * This number does not include any lost frames. 569 * \retval -EIO corrupted indices, no recovery is possible 570 * \retval -EOVERFLOW reader doesn't throttle writer, and frames were lost because reader 571 * isn't keeping up with writer; see \p lost 572 */ 573 ssize_t flush(size_t *lost = NULL); 574 575 /** 576 * Set the hysteresis levels for a throttling reader to wake a blocked writer. 577 * Hysteresis can decrease the number of context switches between reader and a blocking writer. 578 * A non-empty read() or release() by a throttling reader will wake the writer 579 * only if the fill level was > \p armLevel before the read() or release(), 580 * and then the fill level became < \p triggerLevel afterwards. 581 * The default value for \p armLevel is -1, which means always armed. 582 * The default value for \p triggerLevel is mFifo.mFrameCount, 583 * which means every read() or release() will wake the writer. 584 * For hysteresis, \p armLevel must be >= \p triggerLevel - 1. 585 * Decreasing \p armLevel will arm for wakeup, regardless of the current fill level. 586 * Note that the throttling reader is not directly aware of the writer's effective buffer size, 587 * so any change in effective buffer size must be communicated indirectly. 588 * 589 * \param armLevel Arm for wakeup when fill level > this value. 590 * Capped to range [-1, mFifo.mFrameCount]. 591 * \param triggerLevel Trigger wakeup when armed and fill level < this value. 592 * Capped to range [0, mFifo.mFrameCount]. 593 */ 594 void setHysteresis(int32_t armLevel, uint32_t triggerLevel); 595 596 /** 597 * Get the hysteresis levels for waking readers. 598 * 599 * \param armLevel Set to the current arm level in frames. 600 * \param triggerLevel Set to the current trigger level in frames. 601 */ 602 void getHysteresis(int32_t *armLevel, uint32_t *triggerLevel) const; 603 604 /** 605 * Return the total number of lost frames since construction, due to reader not keeping up with 606 * writer. Does not include flushed frames. 607 * It is necessary to call read(), obtain(), or flush() prior to calling this method, 608 * in order to observe an increase in the total, 609 * but it is not necessary for the 'lost' parameter of those prior calls to be non-NULL. 610 * 611 * \return Total lost frames. 612 */ totalLost()613 uint64_t totalLost() const 614 { return mTotalLost; } 615 616 /** 617 * Return the total number of flushed frames since construction. 618 * Does not include lost frames. 619 * 620 * \return Total flushed frames. 621 */ totalFlushed()622 uint64_t totalFlushed() const 623 { return mTotalFlushed; } 624 625 private: 626 // Accessed by reader only using ordinary operations 627 uint32_t mLocalFront; // frame index of first frame slot available to read, or read index 628 629 // Points to shared front index if this reader throttles writer, or NULL if we don't throttle 630 // FIXME consider making it a boolean 631 audio_utils_fifo_index* mThrottleFront; 632 633 bool mFlush; // whether to flush the entire buffer on -EOVERFLOW 634 635 int32_t mArmLevel; // arm if filled > arm level before release() 636 uint32_t mTriggerLevel; // trigger if armed and filled < trigger level after release() 637 bool mIsArmed; // whether currently armed 638 639 uint64_t mTotalLost; // total lost frames, does not include flushed frames 640 uint64_t mTotalFlushed; // total flushed frames, does not include lost frames 641 }; 642 643 #endif // !ANDROID_AUDIO_FIFO_H 644