1/*
2 * Copyright (C) 2012 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 "PipeReader"
18//#define LOG_NDEBUG 0
19
20#include <cutils/compiler.h>
21#include <cutils/atomic.h>
22#include <utils/Log.h>
23#include <media/nbaio/PipeReader.h>
24
25namespace android {
26
27PipeReader::PipeReader(Pipe& pipe) :
28        NBAIO_Source(pipe.mFormat),
29        mPipe(pipe), mFifoReader(mPipe.mFifo, false /*throttlesWriter*/, true /*flush*/),
30        mFramesOverrun(0),
31        mOverruns(0)
32{
33    android_atomic_inc(&pipe.mReaders);
34}
35
36PipeReader::~PipeReader()
37{
38#if !LOG_NDEBUG
39    int32_t readers =
40#else
41    (void)
42#endif
43            android_atomic_dec(&mPipe.mReaders);
44    ALOG_ASSERT(readers > 0);
45}
46
47ssize_t PipeReader::availableToRead()
48{
49    if (CC_UNLIKELY(!mNegotiated)) {
50        return NEGOTIATE;
51    }
52    size_t lost;
53    ssize_t avail = mFifoReader.available(&lost);
54    if (avail == -EOVERFLOW || lost > 0) {
55        mFramesOverrun += lost;
56        ++mOverruns;
57        avail = OVERRUN;
58    }
59    return avail;
60}
61
62ssize_t PipeReader::read(void *buffer, size_t count)
63{
64    size_t lost;
65    ssize_t actual = mFifoReader.read(buffer, count, NULL /*timeout*/, &lost);
66    ALOG_ASSERT(actual <= count);
67    if (actual == -EOVERFLOW || lost > 0) {
68        mFramesOverrun += lost;
69        ++mOverruns;
70        actual = OVERRUN;
71    }
72    if (actual <= 0) {
73        return actual;
74    }
75    mFramesRead += (size_t) actual;
76    return actual;
77}
78
79ssize_t PipeReader::flush()
80{
81    if (CC_UNLIKELY(!mNegotiated)) {
82        return NEGOTIATE;
83    }
84    size_t lost;
85    ssize_t flushed = mFifoReader.flush(&lost);
86    if (flushed == -EOVERFLOW || lost > 0) {
87        mFramesOverrun += lost;
88        ++mOverruns;
89        flushed = OVERRUN;
90    }
91    if (flushed <= 0) {
92        return flushed;
93    }
94    mFramesRead += (size_t) flushed;  // we consider flushed frames as read, but not lost frames
95    return flushed;
96}
97
98}   // namespace android
99