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