| 80 | |
| 81 | /* Sometime the record callback does not return framesize as configured |
| 82 | * (e.g: in OSS), while this module must guarantee returning framesize |
| 83 | * as configured in the creation settings. In this case, we need a buffer |
| 84 | * for the recorded samples. |
| 85 | */ |
| 86 | pj_int16_t *rec_buf; |
| 87 | unsigned rec_buf_size; |
| 88 | |
| 89 | /* Sometime the player callback does not request framesize as configured |
| 90 | * (e.g: in Linux OSS) while sound device will always get samples from |
| 91 | * the other component as many as configured samples_per_frame. |
| 92 | */ |
| 93 | pj_int16_t *play_buf; |
| 94 | unsigned play_buf_size; |
121 | | status = (*stream->rec_cb)(stream->user_data, stream->rec_timestamp, |
122 | | (void*)input, |
123 | | frameCount * stream->bytes_per_sample * |
124 | | stream->channel_count); |
125 | | |
| 135 | /* Calculate number of samples we've got */ |
| 136 | nsamples = frameCount * stream->channel_count + stream->rec_buf_size; |
| 137 | |
| 138 | if (nsamples >= stream->samples_per_frame) |
| 139 | { |
| 140 | /* If buffer is not empty, combine the buffer with the just incoming |
| 141 | * samples, then call put_frame. |
| 142 | */ |
| 143 | if (stream->rec_buf_size) { |
| 144 | unsigned chunk_size = 0; |
| 145 | |
| 146 | chunk_size = stream->samples_per_frame - stream->rec_buf_size; |
| 147 | pjmedia_copy_samples(stream->rec_buf + stream->rec_buf_size, |
| 148 | (pj_int16_t*)input, chunk_size); |
| 149 | status = (*stream->rec_cb)(stream->user_data, stream->rec_timestamp, |
| 150 | (void*) stream->rec_buf, |
| 151 | stream->samples_per_frame * |
| 152 | stream->bytes_per_sample); |
| 153 | |
| 154 | input = (pj_int16_t*) input + chunk_size; |
| 155 | nsamples -= stream->samples_per_frame; |
| 156 | stream->rec_buf_size = 0; |
| 157 | } |
| 158 | |
| 159 | /* Give all frames we have */ |
| 160 | while (nsamples >= stream->samples_per_frame && status == 0) { |
| 161 | status = (*stream->rec_cb)(stream->user_data, stream->rec_timestamp, |
| 162 | (void*) input, |
| 163 | stream->samples_per_frame * |
| 164 | stream->bytes_per_sample); |
| 165 | input = (pj_int16_t*) input + stream->samples_per_frame; |
| 166 | nsamples -= stream->samples_per_frame; |
| 167 | } |
| 168 | |
| 169 | /* Store the remaining samples into the buffer */ |
| 170 | if (nsamples && status == 0) { |
| 171 | stream->rec_buf_size = nsamples; |
| 172 | pjmedia_copy_samples((pj_int16_t*)stream->rec_buf, |
| 173 | (pj_int16_t*)input, nsamples); |
| 174 | } |
| 175 | |
| 176 | } else { |
| 177 | /* Not enough samples, let's just store them in the buffer */ |
| 178 | pjmedia_copy_samples((pj_int16_t*)(stream->rec_buf + |
| 179 | stream->rec_buf_size), |
| 180 | (pj_int16_t*)input, |
| 181 | frameCount * stream->channel_count); |
| 182 | stream->rec_buf_size += frameCount * stream->channel_count; |
| 183 | } |
| 184 | |
174 | | status = (*stream->play_cb)(stream->user_data, stream->play_timestamp, |
175 | | output, size); |
| 230 | /* Check if any buffered samples */ |
| 231 | if (stream->play_buf_size) { |
| 232 | /* samples buffered >= requested by sound device */ |
| 233 | if (stream->play_buf_size >= nsamples_req) { |
| 234 | pjmedia_copy_samples((pj_int16_t*)output, stream->play_buf, |
| 235 | nsamples_req); |
| 236 | stream->play_buf_size -= nsamples_req; |
| 237 | pjmedia_move_samples(stream->play_buf, |
| 238 | stream->play_buf + nsamples_req, |
| 239 | stream->play_buf_size); |
| 240 | nsamples_req = 0; |
| 241 | |
| 242 | return paContinue; |
| 243 | } |
| 244 | |
| 245 | /* samples buffered < requested by sound device */ |
| 246 | pjmedia_copy_samples((pj_int16_t*)output, stream->play_buf, |
| 247 | stream->play_buf_size); |
| 248 | nsamples_req -= stream->play_buf_size; |
| 249 | output = (pj_int16_t*)output + stream->play_buf_size; |
| 250 | stream->play_buf_size = 0; |
| 251 | } |
| 252 | |
| 253 | /* Fill output buffer as requested */ |
| 254 | while (nsamples_req && status == 0) { |
| 255 | if (nsamples_req >= stream->samples_per_frame) { |
| 256 | status = (*stream->play_cb)(stream->user_data, |
| 257 | stream->play_timestamp, |
| 258 | output, |
| 259 | stream->samples_per_frame * |
| 260 | stream->bytes_per_sample); |
| 261 | nsamples_req -= stream->samples_per_frame; |
| 262 | output = (pj_int16_t*)output + stream->samples_per_frame; |
| 263 | } else { |
| 264 | status = (*stream->play_cb)(stream->user_data, |
| 265 | stream->play_timestamp, |
| 266 | stream->play_buf, |
| 267 | stream->samples_per_frame * |
| 268 | stream->bytes_per_sample); |
| 269 | pjmedia_copy_samples((pj_int16_t*)output, stream->play_buf, |
| 270 | nsamples_req); |
| 271 | stream->play_buf_size = stream->samples_per_frame - nsamples_req; |
| 272 | pjmedia_move_samples(stream->play_buf, stream->play_buf+nsamples_req, |
| 273 | stream->play_buf_size); |
| 274 | nsamples_req = 0; |
| 275 | } |
| 276 | } |