| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 1 | /* | 
 | 2 |  * Copyright 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 | #include <cstring> | 
 | 18 | #include <unistd.h> | 
 | 19 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 20 |  | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 21 | #define LOG_TAG "FifoBuffer" | 
 | 22 | //#define LOG_NDEBUG 0 | 
 | 23 | #include <utils/Log.h> | 
 | 24 |  | 
| Phil Burk | f7da0b9 | 2018-04-20 17:24:38 -0700 | [diff] [blame] | 25 | #include <algorithm> | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 26 | #include <memory> | 
| Phil Burk | f7da0b9 | 2018-04-20 17:24:38 -0700 | [diff] [blame] | 27 |  | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 28 | #include "FifoControllerBase.h" | 
 | 29 | #include "FifoController.h" | 
 | 30 | #include "FifoControllerIndirect.h" | 
 | 31 | #include "FifoBuffer.h" | 
 | 32 |  | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 33 | using android::FifoBuffer; | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 34 | using android::FifoBufferAllocated; | 
 | 35 | using android::FifoBufferIndirect; | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 36 | using android::fifo_frames_t; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 37 |  | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 38 | FifoBuffer::FifoBuffer(int32_t bytesPerFrame) | 
 | 39 |         : mBytesPerFrame(bytesPerFrame) {} | 
 | 40 |  | 
 | 41 | FifoBufferAllocated::FifoBufferAllocated(int32_t bytesPerFrame, fifo_frames_t capacityInFrames) | 
 | 42 |         : FifoBuffer(bytesPerFrame) | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 43 | { | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 44 |     mFifo = std::make_unique<FifoController>(capacityInFrames, capacityInFrames); | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 45 |     // allocate buffer | 
 | 46 |     int32_t bytesPerBuffer = bytesPerFrame * capacityInFrames; | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 47 |     mInternalStorage = std::make_unique<uint8_t[]>(bytesPerBuffer); | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 48 |     ALOGV("%s() capacityInFrames = %d, bytesPerFrame = %d", | 
 | 49 |           __func__, capacityInFrames, bytesPerFrame); | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 50 | } | 
 | 51 |  | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 52 | FifoBufferIndirect::FifoBufferIndirect( int32_t   bytesPerFrame, | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 53 |                         fifo_frames_t   capacityInFrames, | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 54 |                         fifo_counter_t *readIndexAddress, | 
 | 55 |                         fifo_counter_t *writeIndexAddress, | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 56 |                         void *  dataStorageAddress | 
 | 57 |                         ) | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 58 |         : FifoBuffer(bytesPerFrame) | 
 | 59 |         , mExternalStorage(static_cast<uint8_t *>(dataStorageAddress)) | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 60 | { | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 61 |     mFifo = std::make_unique<FifoControllerIndirect>(capacityInFrames, | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 62 |                                        capacityInFrames, | 
 | 63 |                                        readIndexAddress, | 
 | 64 |                                        writeIndexAddress); | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 65 | } | 
 | 66 |  | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 67 | int32_t FifoBuffer::convertFramesToBytes(fifo_frames_t frames) { | 
 | 68 |     return frames * mBytesPerFrame; | 
 | 69 | } | 
 | 70 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 71 | void FifoBuffer::fillWrappingBuffer(WrappingBuffer *wrappingBuffer, | 
 | 72 |                                     int32_t framesAvailable, | 
 | 73 |                                     int32_t startIndex) { | 
 | 74 |     wrappingBuffer->data[1] = nullptr; | 
 | 75 |     wrappingBuffer->numFrames[1] = 0; | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 76 |     uint8_t *storage = getStorage(); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 77 |     if (framesAvailable > 0) { | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 78 |         fifo_frames_t capacity = mFifo->getCapacity(); | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 79 |         uint8_t *source = &storage[convertFramesToBytes(startIndex)]; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 80 |         // Does the available data cross the end of the FIFO? | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 81 |         if ((startIndex + framesAvailable) > capacity) { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 82 |             wrappingBuffer->data[0] = source; | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 83 |             fifo_frames_t firstFrames = capacity - startIndex; | 
| Phil Burk | f7da0b9 | 2018-04-20 17:24:38 -0700 | [diff] [blame] | 84 |             wrappingBuffer->numFrames[0] = firstFrames; | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 85 |             wrappingBuffer->data[1] = &storage[0]; | 
| Phil Burk | f7da0b9 | 2018-04-20 17:24:38 -0700 | [diff] [blame] | 86 |             wrappingBuffer->numFrames[1] = framesAvailable - firstFrames; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 87 |         } else { | 
 | 88 |             wrappingBuffer->data[0] = source; | 
 | 89 |             wrappingBuffer->numFrames[0] = framesAvailable; | 
 | 90 |         } | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 91 |     } else { | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 92 |         wrappingBuffer->data[0] = nullptr; | 
 | 93 |         wrappingBuffer->numFrames[0] = 0; | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 94 |     } | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 95 | } | 
 | 96 |  | 
| Phil Burk | fd34a93 | 2017-07-19 07:03:52 -0700 | [diff] [blame] | 97 | fifo_frames_t FifoBuffer::getFullDataAvailable(WrappingBuffer *wrappingBuffer) { | 
| Phil Burk | f7da0b9 | 2018-04-20 17:24:38 -0700 | [diff] [blame] | 98 |     // The FIFO might be overfull so clip to capacity. | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 99 |     fifo_frames_t framesAvailable = std::min(mFifo->getFullFramesAvailable(), | 
 | 100 |                                              mFifo->getCapacity()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 101 |     fifo_frames_t startIndex = mFifo->getReadIndex(); | 
 | 102 |     fillWrappingBuffer(wrappingBuffer, framesAvailable, startIndex); | 
| Phil Burk | fd34a93 | 2017-07-19 07:03:52 -0700 | [diff] [blame] | 103 |     return framesAvailable; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 104 | } | 
 | 105 |  | 
| Phil Burk | fd34a93 | 2017-07-19 07:03:52 -0700 | [diff] [blame] | 106 | fifo_frames_t FifoBuffer::getEmptyRoomAvailable(WrappingBuffer *wrappingBuffer) { | 
| Phil Burk | f7da0b9 | 2018-04-20 17:24:38 -0700 | [diff] [blame] | 107 |     // The FIFO might have underrun so clip to capacity. | 
| Phil Burk | 882c520 | 2018-04-23 10:32:45 -0700 | [diff] [blame] | 108 |     fifo_frames_t framesAvailable = std::min(mFifo->getEmptyFramesAvailable(), | 
 | 109 |                                              mFifo->getCapacity()); | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 110 |     fifo_frames_t startIndex = mFifo->getWriteIndex(); | 
 | 111 |     fillWrappingBuffer(wrappingBuffer, framesAvailable, startIndex); | 
| Phil Burk | fd34a93 | 2017-07-19 07:03:52 -0700 | [diff] [blame] | 112 |     return framesAvailable; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 113 | } | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 114 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 115 | fifo_frames_t FifoBuffer::read(void *buffer, fifo_frames_t numFrames) { | 
 | 116 |     WrappingBuffer wrappingBuffer; | 
 | 117 |     uint8_t *destination = (uint8_t *) buffer; | 
 | 118 |     fifo_frames_t framesLeft = numFrames; | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 119 |  | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 120 |     getFullDataAvailable(&wrappingBuffer); | 
 | 121 |  | 
 | 122 |     // Read data in one or two parts. | 
 | 123 |     int partIndex = 0; | 
 | 124 |     while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) { | 
 | 125 |         fifo_frames_t framesToRead = framesLeft; | 
 | 126 |         fifo_frames_t framesAvailable = wrappingBuffer.numFrames[partIndex]; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 127 |         if (framesAvailable > 0) { | 
 | 128 |             if (framesToRead > framesAvailable) { | 
 | 129 |                 framesToRead = framesAvailable; | 
 | 130 |             } | 
 | 131 |             int32_t numBytes = convertFramesToBytes(framesToRead); | 
 | 132 |             memcpy(destination, wrappingBuffer.data[partIndex], numBytes); | 
 | 133 |  | 
 | 134 |             destination += numBytes; | 
 | 135 |             framesLeft -= framesToRead; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 136 |         } else { | 
 | 137 |             break; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 138 |         } | 
 | 139 |         partIndex++; | 
 | 140 |     } | 
 | 141 |     fifo_frames_t framesRead = numFrames - framesLeft; | 
 | 142 |     mFifo->advanceReadIndex(framesRead); | 
 | 143 |     return framesRead; | 
 | 144 | } | 
 | 145 |  | 
 | 146 | fifo_frames_t FifoBuffer::write(const void *buffer, fifo_frames_t numFrames) { | 
 | 147 |     WrappingBuffer wrappingBuffer; | 
 | 148 |     uint8_t *source = (uint8_t *) buffer; | 
 | 149 |     fifo_frames_t framesLeft = numFrames; | 
 | 150 |  | 
 | 151 |     getEmptyRoomAvailable(&wrappingBuffer); | 
 | 152 |  | 
 | 153 |     // Read data in one or two parts. | 
 | 154 |     int partIndex = 0; | 
 | 155 |     while (framesLeft > 0 && partIndex < WrappingBuffer::SIZE) { | 
 | 156 |         fifo_frames_t framesToWrite = framesLeft; | 
 | 157 |         fifo_frames_t framesAvailable = wrappingBuffer.numFrames[partIndex]; | 
 | 158 |         if (framesAvailable > 0) { | 
 | 159 |             if (framesToWrite > framesAvailable) { | 
 | 160 |                 framesToWrite = framesAvailable; | 
 | 161 |             } | 
 | 162 |             int32_t numBytes = convertFramesToBytes(framesToWrite); | 
 | 163 |             memcpy(wrappingBuffer.data[partIndex], source, numBytes); | 
 | 164 |  | 
 | 165 |             source += numBytes; | 
 | 166 |             framesLeft -= framesToWrite; | 
| Phil Burk | 71f35bb | 2017-04-13 16:05:07 -0700 | [diff] [blame] | 167 |         } else { | 
 | 168 |             break; | 
| Phil Burk | c0c70e3 | 2017-02-09 13:18:38 -0800 | [diff] [blame] | 169 |         } | 
 | 170 |         partIndex++; | 
 | 171 |     } | 
 | 172 |     fifo_frames_t framesWritten = numFrames - framesLeft; | 
 | 173 |     mFifo->advanceWriteIndex(framesWritten); | 
 | 174 |     return framesWritten; | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 175 | } | 
 | 176 |  | 
| Phil Burk | fd911c1 | 2017-01-03 17:15:39 -0800 | [diff] [blame] | 177 | fifo_frames_t FifoBuffer::getThreshold() { | 
 | 178 |     return mFifo->getThreshold(); | 
 | 179 | } | 
 | 180 |  | 
 | 181 | void FifoBuffer::setThreshold(fifo_frames_t threshold) { | 
 | 182 |     mFifo->setThreshold(threshold); | 
 | 183 | } | 
 | 184 |  | 
 | 185 | fifo_frames_t FifoBuffer::getBufferCapacityInFrames() { | 
 | 186 |     return mFifo->getCapacity(); | 
 | 187 | } | 
 | 188 |  | 
| Phil Burk | ea04d97 | 2017-08-07 12:30:44 -0700 | [diff] [blame] | 189 | void FifoBuffer::eraseMemory() { | 
 | 190 |     int32_t numBytes = convertFramesToBytes(getBufferCapacityInFrames()); | 
 | 191 |     if (numBytes > 0) { | 
| Phil Burk | 8f4fe50 | 2020-07-15 23:54:50 +0000 | [diff] [blame] | 192 |         memset(getStorage(), 0, (size_t) numBytes); | 
| Phil Burk | ea04d97 | 2017-08-07 12:30:44 -0700 | [diff] [blame] | 193 |     } | 
 | 194 | } |