1 /*
2 * Copyright (C) 2018 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 #define LOG_TAG "audio_hw_generic_caremu"
18 // #define LOG_NDEBUG 0
19
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 #include <log/log.h>
25
26 #include "audio_vbuffer.h"
27
28 #define MIN(a, b) (((a) < (b)) ? (a) : (b))
29
audio_vbuffer_init(audio_vbuffer_t * audio_vbuffer,size_t frame_count,size_t frame_size)30 int audio_vbuffer_init(audio_vbuffer_t *audio_vbuffer, size_t frame_count,
31 size_t frame_size) {
32 if (!audio_vbuffer) {
33 return -EINVAL;
34 }
35 audio_vbuffer->frame_size = frame_size;
36 audio_vbuffer->frame_count = frame_count;
37 size_t bytes = frame_count * frame_size;
38 audio_vbuffer->data = calloc(bytes, 1);
39 if (!audio_vbuffer->data) {
40 return -ENOMEM;
41 }
42 audio_vbuffer->head = 0;
43 audio_vbuffer->tail = 0;
44 audio_vbuffer->live = 0;
45 pthread_mutex_init(&audio_vbuffer->lock, (const pthread_mutexattr_t *)NULL);
46 return 0;
47 }
48
audio_vbuffer_destroy(audio_vbuffer_t * audio_vbuffer)49 int audio_vbuffer_destroy(audio_vbuffer_t *audio_vbuffer) {
50 if (!audio_vbuffer) {
51 return -EINVAL;
52 }
53 free(audio_vbuffer->data);
54 pthread_mutex_destroy(&audio_vbuffer->lock);
55 return 0;
56 }
57
audio_vbuffer_live(audio_vbuffer_t * audio_vbuffer)58 int audio_vbuffer_live(audio_vbuffer_t *audio_vbuffer) {
59 if (!audio_vbuffer) {
60 return -EINVAL;
61 }
62 pthread_mutex_lock(&audio_vbuffer->lock);
63 int live = audio_vbuffer->live;
64 pthread_mutex_unlock(&audio_vbuffer->lock);
65 return live;
66 }
67
audio_vbuffer_dead(audio_vbuffer_t * audio_vbuffer)68 int audio_vbuffer_dead(audio_vbuffer_t *audio_vbuffer) {
69 if (!audio_vbuffer) {
70 return -EINVAL;
71 }
72 pthread_mutex_lock(&audio_vbuffer->lock);
73 int dead = audio_vbuffer->frame_count - audio_vbuffer->live;
74 pthread_mutex_unlock(&audio_vbuffer->lock);
75 return dead;
76 }
77
audio_vbuffer_write(audio_vbuffer_t * audio_vbuffer,const void * buffer,size_t frame_count)78 size_t audio_vbuffer_write(audio_vbuffer_t *audio_vbuffer, const void *buffer,
79 size_t frame_count) {
80 size_t frames_written = 0;
81 pthread_mutex_lock(&audio_vbuffer->lock);
82
83 while (frame_count != 0) {
84 int frames = 0;
85 if (audio_vbuffer->live == 0 || audio_vbuffer->head > audio_vbuffer->tail) {
86 frames =
87 MIN(frame_count, audio_vbuffer->frame_count - audio_vbuffer->head);
88 } else if (audio_vbuffer->head < audio_vbuffer->tail) {
89 frames = MIN(frame_count, audio_vbuffer->tail - (audio_vbuffer->head));
90 } else {
91 ALOGV("%s audio_vbuffer is full", __func__);
92 break;
93 }
94 memcpy(
95 &audio_vbuffer->data[audio_vbuffer->head * audio_vbuffer->frame_size],
96 &((uint8_t *)buffer)[frames_written * audio_vbuffer->frame_size],
97 frames * audio_vbuffer->frame_size);
98 audio_vbuffer->live += frames;
99 frames_written += frames;
100 frame_count -= frames;
101 audio_vbuffer->head =
102 (audio_vbuffer->head + frames) % audio_vbuffer->frame_count;
103 }
104
105 pthread_mutex_unlock(&audio_vbuffer->lock);
106 return frames_written;
107 }
108
audio_vbuffer_read(audio_vbuffer_t * audio_vbuffer,void * buffer,size_t frame_count)109 size_t audio_vbuffer_read(audio_vbuffer_t *audio_vbuffer, void *buffer,
110 size_t frame_count) {
111 size_t frames_read = 0;
112 pthread_mutex_lock(&audio_vbuffer->lock);
113
114 while (frame_count != 0) {
115 int frames = 0;
116 if (audio_vbuffer->live == audio_vbuffer->frame_count ||
117 audio_vbuffer->tail > audio_vbuffer->head) {
118 frames =
119 MIN(frame_count, audio_vbuffer->frame_count - audio_vbuffer->tail);
120 } else if (audio_vbuffer->tail < audio_vbuffer->head) {
121 frames = MIN(frame_count, audio_vbuffer->head - audio_vbuffer->tail);
122 } else {
123 break;
124 }
125 memcpy(
126 &((uint8_t *)buffer)[frames_read * audio_vbuffer->frame_size],
127 &audio_vbuffer->data[audio_vbuffer->tail * audio_vbuffer->frame_size],
128 frames * audio_vbuffer->frame_size);
129 audio_vbuffer->live -= frames;
130 frames_read += frames;
131 frame_count -= frames;
132 audio_vbuffer->tail =
133 (audio_vbuffer->tail + frames) % audio_vbuffer->frame_count;
134 }
135
136 pthread_mutex_unlock(&audio_vbuffer->lock);
137 return frames_read;
138 }
139