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 #ifndef FIFO_FIFO_BUFFER_H
18 #define FIFO_FIFO_BUFFER_H
19 
20 #include <memory>
21 #include <stdint.h>
22 
23 #include "FifoControllerBase.h"
24 
25 namespace android {
26 
27 /**
28  * Structure that represents a region in a circular buffer that might be at the
29  * end of the array and split in two.
30  */
31 struct WrappingBuffer {
32     enum {
33         SIZE = 2
34     };
35     void *data[SIZE];
36     int32_t numFrames[SIZE];
37 };
38 
39 class FifoBuffer {
40 public:
41     FifoBuffer(int32_t bytesPerFrame, fifo_frames_t capacityInFrames);
42 
43     FifoBuffer(int32_t bytesPerFrame,
44                fifo_frames_t capacityInFrames,
45                fifo_counter_t *readCounterAddress,
46                fifo_counter_t *writeCounterAddress,
47                void *dataStorageAddress);
48 
49     ~FifoBuffer();
50 
51     int32_t convertFramesToBytes(fifo_frames_t frames);
52 
53     fifo_frames_t read(void *destination, fifo_frames_t framesToRead);
54 
55     fifo_frames_t write(const void *source, fifo_frames_t framesToWrite);
56 
57     fifo_frames_t getThreshold();
58 
59     void setThreshold(fifo_frames_t threshold);
60 
61     fifo_frames_t getBufferCapacityInFrames();
62 
63     /**
64      * Return pointer to available full frames in data1 and set size in numFrames1.
65      * if the data is split across the end of the FIFO then set data2 and numFrames2.
66      * Other wise set them to null
67      * @param wrappingBuffer
68      * @return total full frames available
69      */
70     fifo_frames_t getFullDataAvailable(WrappingBuffer *wrappingBuffer);
71 
72     /**
73      * Return pointer to available empty frames in data1 and set size in numFrames1.
74      * if the room is split across the end of the FIFO then set data2 and numFrames2.
75      * Other wise set them to null
76      * @param wrappingBuffer
77      * @return total empty frames available
78      */
79     fifo_frames_t getEmptyRoomAvailable(WrappingBuffer *wrappingBuffer);
80 
getBytesPerFrame()81     int32_t getBytesPerFrame() {
82         return mBytesPerFrame;
83     }
84 
85     // Proxy methods for the internal FifoController
86 
getReadCounter()87     fifo_counter_t getReadCounter() {
88         return mFifo->getReadCounter();
89     }
90 
setReadCounter(fifo_counter_t n)91     void setReadCounter(fifo_counter_t n) {
92         mFifo->setReadCounter(n);
93     }
94 
getWriteCounter()95     fifo_counter_t getWriteCounter() {
96         return mFifo->getWriteCounter();
97     }
98 
setWriteCounter(fifo_counter_t n)99     void setWriteCounter(fifo_counter_t n) {
100         mFifo->setWriteCounter(n);
101     }
102 
advanceReadIndex(fifo_frames_t numFrames)103     void advanceReadIndex(fifo_frames_t numFrames) {
104         mFifo->advanceReadIndex(numFrames);
105     }
106 
advanceWriteIndex(fifo_frames_t numFrames)107     void advanceWriteIndex(fifo_frames_t numFrames) {
108         mFifo->advanceWriteIndex(numFrames);
109     }
110 
getEmptyFramesAvailable()111     fifo_frames_t getEmptyFramesAvailable() {
112         return mFifo->getEmptyFramesAvailable();
113     }
114 
getFullFramesAvailable()115     fifo_frames_t getFullFramesAvailable() {
116         return mFifo->getFullFramesAvailable();
117     }
118 
119     /*
120      * This is generally only called before or after the buffer is used.
121      */
122     void eraseMemory();
123 
124 private:
125 
126     void fillWrappingBuffer(WrappingBuffer *wrappingBuffer,
127                             int32_t framesAvailable, int32_t startIndex);
128 
129     const int32_t             mBytesPerFrame;
130     // We do not use a std::unique_ptr for mStorage because it is often a pointer to
131     // memory shared between processes and cannot be deleted trivially.
132     uint8_t                  *mStorage = nullptr;
133     bool                      mStorageOwned = false; // did this object allocate the storage?
134     std::unique_ptr<FifoControllerBase> mFifo{};
135 };
136 
137 }  // android
138 
139 #endif //FIFO_FIFO_BUFFER_H
140