access: srt: add support stream encryption
[vlc.git] / modules / audio_output / TPCircularBuffer.h
blobb4932edeb2996d943d8d5905e8eb6447ea7477ae
1 //
2 // TPCircularBuffer.h
3 // Circular/Ring buffer implementation
4 //
5 // https://github.com/michaeltyson/TPCircularBuffer
6 //
7 // Created by Michael Tyson on 10/12/2011.
8 // Copyright 2011-2012 A Tasty Pixel. All rights reserved.
9 //
11 // This implementation makes use of a virtual memory mapping technique that inserts a virtual copy
12 // of the buffer memory directly after the buffer's end, negating the need for any buffer wrap-around
13 // logic. Clients can simply use the returned memory address as if it were contiguous space.
15 // The implementation is thread-safe in the case of a single producer and single consumer.
17 // Virtual memory technique originally proposed by Philip Howard (http://vrb.slashusr.org/), and
18 // adapted to Darwin by Kurt Revis (http://www.snoize.com,
19 // http://www.snoize.com/Code/PlayBufferedSoundFile.tar.gz)
22 #ifndef TPCircularBuffer_h
23 #define TPCircularBuffer_h
25 #include <libkern/OSAtomic.h>
26 #include <string.h>
27 #include <assert.h>
29 #ifdef __cplusplus
30 extern "C" {
31 #endif
33 typedef struct {
34 void *buffer;
35 int32_t length;
36 int32_t tail;
37 int32_t head;
38 volatile int32_t fillCount;
39 } TPCircularBuffer;
41 /*!
42 * Initialise buffer
44 * Note that the length is advisory only: Because of the way the
45 * memory mirroring technique works, the true buffer length will
46 * be multiples of the device page size (e.g. 4096 bytes)
48 * @param buffer Circular buffer
49 * @param length Length of buffer
51 bool TPCircularBufferInit(TPCircularBuffer *buffer, int32_t length);
53 /*!
54 * Cleanup buffer
56 * Releases buffer resources.
58 void TPCircularBufferCleanup(TPCircularBuffer *buffer);
60 /*!
61 * Clear buffer
63 * Resets buffer to original, empty state.
65 * This is safe for use by consumer while producer is accessing
66 * buffer.
68 void TPCircularBufferClear(TPCircularBuffer *buffer);
70 // Reading (consuming)
72 /*!
73 * Access end of buffer
75 * This gives you a pointer to the end of the buffer, ready
76 * for reading, and the number of available bytes to read.
78 * @param buffer Circular buffer
79 * @param availableBytes On output, the number of bytes ready for reading
80 * @return Pointer to the first bytes ready for reading, or NULL if buffer is empty
82 static __inline__ __attribute__((always_inline)) void* TPCircularBufferTail(TPCircularBuffer *buffer, int32_t* availableBytes) {
83 *availableBytes = buffer->fillCount;
84 if ( *availableBytes == 0 ) return NULL;
85 return (void*)((char*)buffer->buffer + buffer->tail);
88 /*!
89 * Consume bytes in buffer
91 * This frees up the just-read bytes, ready for writing again.
93 * @param buffer Circular buffer
94 * @param amount Number of bytes to consume
96 static __inline__ __attribute__((always_inline)) void TPCircularBufferConsume(TPCircularBuffer *buffer, int32_t amount) {
97 buffer->tail = (buffer->tail + amount) % buffer->length;
98 OSAtomicAdd32Barrier(-amount, &buffer->fillCount);
99 assert(buffer->fillCount >= 0);
103 * Version of TPCircularBufferConsume without the memory barrier, for more optimal use in single-threaded contexts
105 static __inline__ __attribute__((always_inline)) void TPCircularBufferConsumeNoBarrier(TPCircularBuffer *buffer, int32_t amount) {
106 buffer->tail = (buffer->tail + amount) % buffer->length;
107 buffer->fillCount -= amount;
108 assert(buffer->fillCount >= 0);
112 * Access front of buffer
114 * This gives you a pointer to the front of the buffer, ready
115 * for writing, and the number of available bytes to write.
117 * @param buffer Circular buffer
118 * @param availableBytes On output, the number of bytes ready for writing
119 * @return Pointer to the first bytes ready for writing, or NULL if buffer is full
121 static __inline__ __attribute__((always_inline)) void* TPCircularBufferHead(TPCircularBuffer *buffer, int32_t* availableBytes) {
122 *availableBytes = (buffer->length - buffer->fillCount);
123 if ( *availableBytes == 0 ) return NULL;
124 return (void*)((char*)buffer->buffer + buffer->head);
127 // Writing (producing)
130 * Produce bytes in buffer
132 * This marks the given section of the buffer ready for reading.
134 * @param buffer Circular buffer
135 * @param amount Number of bytes to produce
137 static __inline__ __attribute__((always_inline)) void TPCircularBufferProduce(TPCircularBuffer *buffer, int amount) {
138 buffer->head = (buffer->head + amount) % buffer->length;
139 OSAtomicAdd32Barrier(amount, &buffer->fillCount);
140 assert(buffer->fillCount <= buffer->length);
144 * Version of TPCircularBufferProduce without the memory barrier, for more optimal use in single-threaded contexts
146 static __inline__ __attribute__((always_inline)) void TPCircularBufferProduceNoBarrier(TPCircularBuffer *buffer, int amount) {
147 buffer->head = (buffer->head + amount) % buffer->length;
148 buffer->fillCount += amount;
149 assert(buffer->fillCount <= buffer->length);
153 * Helper routine to copy bytes to buffer
155 * This copies the given bytes to the buffer, and marks them ready for writing.
157 * @param buffer Circular buffer
158 * @param src Source buffer
159 * @param len Number of bytes in source buffer
160 * @return true if bytes copied, false if there was insufficient space
162 static __inline__ __attribute__((always_inline)) bool TPCircularBufferProduceBytes(TPCircularBuffer *buffer, const void* src, int32_t len) {
163 int32_t space;
164 void *ptr = TPCircularBufferHead(buffer, &space);
165 if ( space < len ) return false;
166 memcpy(ptr, src, len);
167 TPCircularBufferProduce(buffer, len);
168 return true;
171 #ifdef __cplusplus
173 #endif
175 #endif