summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'audio/utils/src/SimpleStream.cpp')
-rw-r--r--audio/utils/src/SimpleStream.cpp605
1 files changed, 605 insertions, 0 deletions
diff --git a/audio/utils/src/SimpleStream.cpp b/audio/utils/src/SimpleStream.cpp
new file mode 100644
index 0000000..5b1ddd5
--- /dev/null
+++ b/audio/utils/src/SimpleStream.cpp
@@ -0,0 +1,605 @@
1/*
2 * Copyright (C) 2013 Texas Instruments
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_NDEBUG 0
18// #define VERY_VERBOSE_LOGGING
19
20#include <tiaudioutils/Log.h>
21#include <tiaudioutils/SimpleStream.h>
22#include <tiaudioutils/Resampler.h>
23
24namespace tiaudioutils {
25
26SimpleInStream::SimpleInStream(const PcmParams &params)
27 : mParams(params), mReader(NULL), mStarted(false)
28{
29}
30
31SimpleInStream::~SimpleInStream()
32{
33 if (mReader) {
34 ALOGW("SimpleInStream: automatically unregistered");
35 mReader->unregisterStream(this);
36 }
37}
38
39bool SimpleInStream::initCheck() const
40{
41 if (!mParams.isValid()) {
42 ALOGE("SimpleInStream: params are invalid");
43 return false;
44 }
45
46 if (!mParams.frameCount) {
47 ALOGE("SimpleInStream: params.frameCount is invalid");
48 return false;
49 }
50
51 return true;
52}
53
54int SimpleInStream::start()
55{
56 if (!mReader) {
57 ALOGE("SimpleInStream: not registered to reader, cannot start");
58 return -EINVAL;
59 }
60
61 AutoMutex lock(mLock);
62 if (mStarted) {
63 ALOGE("SimpleInStream: stream is already started");
64 return -EBUSY;
65 }
66
67 int ret = mReader->open();
68 if (!ret)
69 mStarted = true;
70 else
71 ALOGE("SimpleInStream: failed to open %d", ret);
72
73 return ret;
74}
75
76void SimpleInStream::stop()
77{
78 if (!mReader) {
79 ALOGE("SimpleInStream: not registered to reader, cannot stop");
80 return;
81 }
82
83 AutoMutex lock(mLock);
84 if (!mStarted) {
85 ALOGE("SimpleInStream: stream is already stopped");
86 return;
87 }
88
89 mStarted = false;
90 mReader->close();
91}
92
93bool SimpleInStream::isStarted() const
94{
95 AutoMutex lock(mLock);
96 return mStarted;
97}
98
99int SimpleInStream::read(void *buffer, size_t frames)
100{
101 if (!mReader) {
102 ALOGE("SimpleInStream: not registered to reader, cannot read");
103 return -EINVAL;
104 }
105
106 AutoMutex lock(mLock);
107 if (!mStarted) {
108 ALOGE("SimpleInStream: stream is not started, cannot read");
109 return -EPERM;
110 }
111
112 return mReader->read(buffer, frames);
113}
114
115/* ---------------------------------------------------------------------------------------- */
116
117SimpleOutStream::SimpleOutStream(const PcmParams &params)
118 : mParams(params), mWriter(NULL), mStarted(false)
119{
120}
121
122SimpleOutStream::~SimpleOutStream()
123{
124 if (mWriter) {
125 ALOGW("SimpleOutStream: automatically unregistered");
126 mWriter->unregisterStream(this);
127 }
128}
129
130bool SimpleOutStream::initCheck() const
131{
132 if (!mParams.isValid()) {
133 ALOGE("SimpleOutStream: params are invalid");
134 return false;
135 }
136
137 if (!mParams.frameCount) {
138 ALOGE("SimpleOutStream: params.frameCount is invalid");
139 return false;
140 }
141
142 return true;
143}
144
145int SimpleOutStream::start()
146{
147 if (!mWriter) {
148 ALOGE("SimpleOutStream: not registered to writer, cannot start");
149 return -EINVAL;
150 }
151
152 AutoMutex lock(mLock);
153 if (mStarted) {
154 ALOGE("SimpleOutStream: stream is already started");
155 return -EBUSY;
156 }
157
158 int ret = mWriter->open();
159 if (!ret)
160 mStarted = true;
161 else
162 ALOGE("SimpleOutStream: failed to open %d", ret);
163
164 return ret;
165}
166
167void SimpleOutStream::stop()
168{
169 if (!mWriter) {
170 ALOGE("SimpleOutStream: not registered to writer, cannot stop");
171 return;
172 }
173
174 AutoMutex lock(mLock);
175 if (!mStarted) {
176 ALOGE("SimpleOutStream: stream is already stopped");
177 return;
178 }
179
180 mStarted = false;
181 mWriter->close();
182}
183
184bool SimpleOutStream::isStarted() const
185{
186 AutoMutex lock(mLock);
187 return mStarted;
188}
189
190int SimpleOutStream::write(const void *buffer, size_t frames)
191{
192 if (!mWriter) {
193 ALOGE("SimpleOutStream: not registered to writer, cannot write");
194 return -EINVAL;
195 }
196
197 AutoMutex lock(mLock);
198 if (!mStarted) {
199 ALOGE("SimpleOutStream: stream is not started, cannot write");
200 return -EPERM;
201 }
202
203 return mWriter->write(buffer, frames);
204}
205
206/* ---------------------------------------------------------------------------------------- */
207
208SimpleReader::SimpleReader(PcmInPort *port, const PcmParams &params)
209 : mPort(port),
210 mParams(params),
211 mStream(NULL),
212 mResampler(NULL),
213 mBufferProvider(*this)
214{
215 /* Intermediate buffer for the frames to be resampled */
216 mBuffer.frameCount = mParams.frameCount;
217 mBuffer.i8 = new int8_t[mParams.bufferSize()];
218}
219
220SimpleReader::~SimpleReader()
221{
222 if (mBuffer.i8)
223 delete [] mBuffer.i8;
224}
225
226bool SimpleReader::initCheck() const
227{
228 if (mPort == NULL) {
229 ALOGE("SimpleReader: invalid PCM input port");
230 return false;
231 }
232
233 if (!mParams.isValid() || !mParams.frameCount) {
234 ALOGE("SimpleReader: params are not valid");
235 return false;
236 }
237
238 if (mBuffer.raw == NULL) {
239 ALOGE("SimpleReader: intermediate buffer allocation failed");
240 return false;
241 }
242
243 return true;
244}
245
246int SimpleReader::registerStream(SimpleInStream *stream)
247{
248 if (!stream) {
249 ALOGE("SimpleReader: stream is invalid, cannot register");
250 return -EINVAL;
251 }
252
253 const PcmParams &outParams = stream->getParams();
254 if (!outParams.isValid() || !outParams.frameCount) {
255 ALOGE("SimpleReader: stream has invalid params");
256 return -EINVAL;
257 }
258
259 ALOGI("SimpleReader: register stream %p", stream);
260
261 AutoMutex lock(mLock);
262 if (mStream) {
263 ALOGE("SimpleReader: reader allows only one stream");
264 return -ENOTSUP;
265 }
266
267 /*
268 * Hardware parameters are not known when the stream is created. It's until
269 * stream registration that we have enough information to determine if the
270 * stream needs resampling, and if so, what the resampling parameters are.
271 * Speex-based resampler is supported only for 16-bits/sample.
272 */
273 if ((mParams.sampleRate != outParams.sampleRate) && (outParams.sampleBits == 16)) {
274 mResampler = new Resampler(mParams, outParams);
275 if (!mResampler) {
276 ALOGE("SimpleReader: failed to create resampler");
277 return -ENODEV;
278 }
279 if (!mResampler->initCheck()) {
280 ALOGE("SimpleReader: failed to initialize resampler");
281 delete mResampler;
282 mResampler = NULL;
283 return -EINVAL;
284 }
285 } else if ((mParams.sampleBits != outParams.sampleBits) ||
286 (mParams.channels != outParams.channels) ||
287 (mParams.sampleRate != outParams.sampleRate)) {
288 ALOGE("SimpleReader: reader doesn't support stream's params");
289 return -EINVAL;
290 }
291
292 stream->mReader = this;
293 mStream = stream;
294
295 return 0;
296}
297
298void SimpleReader::unregisterStream(SimpleInStream *stream)
299{
300 if (!stream) {
301 ALOGE("SimpleReader: stream is invalid, cannot unregister");
302 return;
303 }
304
305 if (stream->isStarted()) {
306 ALOGE("SimpleReader: stream %p is not stopped, cannot unregister", stream);
307 return;
308 }
309
310 ALOGI("SimpleReader: unregister stream %p", stream);
311
312 AutoMutex lock(mLock);
313 if (mStream != stream) {
314 ALOGE("SimpleReader: stream is already unregistered");
315 return;
316 }
317
318 if (mResampler) {
319 delete mResampler;
320 mResampler = NULL;
321 }
322
323 stream->mReader = NULL;
324 mStream = NULL;
325}
326
327int SimpleReader::open()
328{
329 ALOGI("SimpleReader: open PCM port");
330
331 AutoMutex lock(mLock);
332 if (mPort->isOpen()) {
333 ALOGW("SimpleReader: port is already open");
334 return 0;
335 }
336
337 int ret = mPort->open(mParams);
338 if (ret)
339 ALOGE("SimpleReader: failed to open PCM port %d", ret);
340
341 return ret;
342}
343
344void SimpleReader::close()
345{
346 ALOGI("SimpleReader: close PCM port");
347
348 AutoMutex lock(mLock);
349 if (mPort->isOpen())
350 mPort->close();
351 else
352 ALOGW("SimpleReader: PCM port is already closed");
353}
354
355
356int SimpleReader::read(void *buffer, size_t frames)
357{
358 AutoMutex lock(mLock);
359 int ret;
360
361 if (!mPort->isOpen()) {
362 ALOGE("SimpleReader: PCM port is not open");
363 return -ENODEV;
364 }
365
366 if (mResampler) {
367 ret = mResampler->resample(mBufferProvider,
368 buffer, frames);
369 if (ret) {
370 ALOGE("SimpleReader: failed to resample %d", ret);
371 return ret;
372 }
373 ret = frames;
374 } else {
375 ret = mPort->read(buffer, frames);
376 if (ret < 0)
377 ALOGE("SimpleReader: failed to read PCM data %d", ret);
378 }
379
380 return ret;
381}
382
383/* ---------------------------------------------------------------------------------------- */
384
385int SimpleReader::ReadProvider::getNextBuffer(BufferProvider::Buffer *buffer)
386{
387 /* resize buffer if needed */
388 if (buffer->frameCount > mReader.mBuffer.frameCount) {
389 delete [] mReader.mBuffer.i8;
390 mReader.mBuffer.i8 = new int8_t[buffer->frameCount * mReader.mParams.frameSize()];
391 if (mReader.mBuffer.i8) {
392 ALOGE("SimpleReader: failed to resize internal buffer");
393 return -ENOMEM;
394 }
395 mReader.mBuffer.frameCount = buffer->frameCount;
396 }
397
398 int8_t *curBuffer = mReader.mBuffer.i8;
399 uint32_t pending = buffer->frameCount;
400 while (pending > 0) {
401 int read = mReader.mPort->read(curBuffer, pending);
402 if (read < 0) {
403 ALOGE("SimpleReader: failed to read PCM data %d", read);
404 break;
405 }
406 pending -= read;
407 curBuffer += read * mReader.mParams.frameSize();
408 }
409
410 buffer->raw = mReader.mBuffer.raw;
411 buffer->frameCount -= pending;
412
413 ALOGW_IF(pending, "SimpleReader: could not read %d frames", pending);
414
415 return 0;
416}
417
418void SimpleReader::ReadProvider::releaseBuffer(BufferProvider::Buffer *buffer)
419{
420 /* Nothing to do to release the buffer, but must be implemented */
421}
422
423/* ---------------------------------------------------------------------------------------- */
424
425SimpleWriter::SimpleWriter(PcmOutPort *port, const PcmParams &params)
426 : mPort(port),
427 mParams(params),
428 mStream(NULL),
429 mResampler(NULL)
430{
431 /* Intermediate buffer for the resampled frames */
432 mBuffer.frameCount = mParams.frameCount;
433 mBuffer.i8 = new int8_t[mParams.bufferSize()];
434}
435
436SimpleWriter::~SimpleWriter()
437{
438 if (mBuffer.i8)
439 delete [] mBuffer.i8;
440}
441
442bool SimpleWriter::initCheck() const
443{
444 if (mPort == NULL) {
445 ALOGE("SimpleWriter: invalid PCM output port");
446 return false;
447 }
448
449 if (!mParams.isValid() || !mParams.frameCount) {
450 ALOGE("SimpleWriter: params are not valid");
451 return false;
452 }
453
454 if (mBuffer.raw == NULL) {
455 ALOGE("SimpleWriter: intermediate buffer allocation failed");
456 return false;
457 }
458
459 return true;
460}
461
462int SimpleWriter::registerStream(SimpleOutStream *stream)
463{
464 if (!stream) {
465 ALOGE("SimpleWriter: stream is invalid, cannot register");
466 return -EINVAL;
467 }
468
469 const PcmParams &inParams = stream->getParams();
470 if (!inParams.isValid() || !inParams.frameCount) {
471 ALOGE("SimpleWriter: stream has invalid params");
472 return -EINVAL;
473 }
474
475 ALOGI("SimpleWriter: register stream %p", stream);
476
477 AutoMutex lock(mLock);
478 if (mStream) {
479 ALOGE("SimpleWriter: writer allows only one stream");
480 return -ENOTSUP;
481 }
482
483 /*
484 * Hardware parameters are not known when the stream is created. It's until
485 * stream registration that we have enough information to determine if the
486 * stream needs resampling, and if so, what the resampling parameters are.
487 * Speex-based resampler is supported only for 16-bits/sample.
488 */
489 if ((mParams.sampleRate != inParams.sampleRate) && (inParams.sampleBits == 16)) {
490 mResampler = new Resampler(inParams, mParams);
491 if (!mResampler) {
492 ALOGE("SimpleWriter: failed to create resampler");
493 return -ENODEV;
494 }
495 if (!mResampler->initCheck()) {
496 ALOGE("SimpleWriter: failed to initialize resampler");
497 delete mResampler;
498 mResampler = NULL;
499 return -EINVAL;
500 }
501 } else if ((mParams.sampleBits != inParams.sampleBits) ||
502 (mParams.channels != inParams.channels) ||
503 (mParams.sampleRate != inParams.sampleRate)) {
504 ALOGE("SimpleWriter: writer doesn't support stream's params");
505 return -EINVAL;
506 }
507
508 stream->mWriter = this;
509 mStream = stream;
510
511 return 0;
512}
513
514void SimpleWriter::unregisterStream(SimpleOutStream *stream)
515{
516 if (!stream) {
517 ALOGE("SimpleWriter: stream is invalid, cannot unregister");
518 return;
519 }
520
521 if (stream->isStarted()) {
522 ALOGE("SimpleWriter: stream %p is not stopped, cannot unregister", stream);
523 return;
524 }
525
526 ALOGI("SimpleWriter: unregister stream %p", stream);
527
528 AutoMutex lock(mLock);
529 if (mStream != stream) {
530 ALOGE("SimpleWriter: stream is already unregistered");
531 return;
532 }
533
534 if (mResampler) {
535 delete mResampler;
536 mResampler = NULL;
537 }
538
539 stream->mWriter = NULL;
540 mStream = NULL;
541}
542
543int SimpleWriter::open()
544{
545 ALOGI("SimpleWriter: open PCM port");
546
547 AutoMutex lock(mLock);
548 if (mPort->isOpen()) {
549 ALOGW("SimpleWriter: port is already open");
550 return 0;
551 }
552
553 int ret = mPort->open(mParams);
554 if (ret)
555 ALOGE("SimpleWriter: failed to open PCM port %d", ret);
556
557 return ret;
558}
559
560void SimpleWriter::close()
561{
562 ALOGI("SimpleWriter: close PCM port");
563
564 AutoMutex lock(mLock);
565 if (mPort->isOpen())
566 mPort->close();
567 else
568 ALOGW("SimpleWriter: PCM port is already closed");
569}
570
571
572int SimpleWriter::write(const void *buffer, size_t frames)
573{
574 AutoMutex lock(mLock);
575
576 if (!mPort->isOpen()) {
577 ALOGE("SimpleWriter: PCM port is not open");
578 return -ENODEV;
579 }
580
581 const void *outBuffer;
582 uint32_t outFrames;
583 int ret;
584
585 if (mResampler) {
586 outBuffer = mBuffer.raw;
587 outFrames = mBuffer.frameCount;
588 ret = mResampler->resample(buffer, frames, mBuffer.raw, outFrames);
589 if (ret) {
590 ALOGE("SimpleWriter: failed to resample %d", ret);
591 return ret;
592 }
593 } else {
594 outBuffer = buffer;
595 outFrames = frames;
596 }
597
598 ret = mPort->write(outBuffer, outFrames);
599 if (ret < 0)
600 ALOGE("SimpleWriter: failed to write PCM data %d", ret);
601
602 return ret;
603}
604
605} /* namespace tiaudioutils */