summaryrefslogtreecommitdiff
path: root/libaudio/AudioStreamOut.h
blob: a33b91a0001b0e873c224072e5e2047a5c79d8ba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
**
** Copyright 2012, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
** you may not use this file except in compliance with the License.
** You may obtain a copy of the License at
**
**     http://www.apache.org/licenses/LICENSE-2.0
**
** Unless required by applicable law or agreed to in writing, software
** distributed under the License is distributed on an "AS IS" BASIS,
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
** See the License for the specific language governing permissions and
** limitations under the License.
*/

#ifndef ANDROID_AUDIO_STREAM_OUT_H
#define ANDROID_AUDIO_STREAM_OUT_H

#include <stdint.h>
#include <sys/types.h>

#include <common_time/local_clock.h>
#include <hardware/audio.h>
#include <media/AudioParameter.h>

#include "AudioOutput.h"

namespace android {

class AudioHardwareOutput;

class AudioStreamOut {
  public:
    AudioStreamOut(AudioHardwareOutput& owner, bool mcOut, bool isIec958NonAudio);
    ~AudioStreamOut();

    uint32_t            latency() const;
    status_t            getRenderPosition(uint32_t *dspFrames);
    status_t            getPresentationPosition(uint64_t *frames, struct timespec *timestamp);
    status_t            getNextWriteTimestamp(int64_t *timestamp);
    status_t            standby();
    status_t            pause();
    status_t            resume();
    status_t            flush();
    status_t            dump(int fd);

    uint32_t            sampleRate()        const { return mInputSampleRate; }
    uint32_t            outputSampleRate()  const;

    size_t              bufferSize()        const { return mInputBufSize; }
    uint32_t            chanMask()          const { return mInputChanMask; }
    audio_format_t      format()            const { return mInputFormat; }
    uint32_t            framesPerChunk()    const { return mInputChunkFrames; }
    uint32_t            nomChunksInFlight() const { return mInputNominalChunksInFlight; }

    status_t            set(audio_format_t *pFormat,
                            uint32_t       *pChannels,
                            uint32_t       *pRate);
    void                setTgtDevices(uint32_t tgtDevices);

    status_t            setParameters(struct audio_stream *stream,
                                      const char *kvpairs);
    char*               getParameters(const char* keys);
    const char*         getName() const { return mIsMCOutput ? "Multi-channel"
                                                             : "Main"; }

    ssize_t             write(const void* buffer, size_t bytes);

    bool                isIec958NonAudio() const { return mIsIec958NonAudio; }

protected:
    // Lock in this order to avoid deadlock.
    //    mRoutingLock
    //    mPresentationLock

    // Track frame position for timestamps, etc.
    uint64_t        mRenderPosition;  // in frames, increased by write
    uint64_t        mFramesPresented; // increased by write

    // Cache of the last PresentationPosition.
    // This cache is used in case of retrograde timestamps or if the mRoutingLock is held.
    Mutex           mPresentationLock; // protects these mLastPresentation* variables
    uint64_t        mLastPresentationPosition; // frames
    struct timespec mLastPresentationTime;
    bool            mLastPresentationValid;

    // Our HAL, used as the middle-man to collect and trade AudioOutputs.
    AudioHardwareOutput&  mOwnerHAL;

    // Details about the format of the audio we have been configured to receive
    // from audio flinger.
    uint32_t        mInputSampleRate;
    uint32_t        mInputChanMask;
    audio_format_t  mInputFormat;
    uint32_t        mInputNominalChunksInFlight;

    // Handy values pre-computed from the audio configuration.
    uint32_t        mInputBufSize;
    uint32_t        mInputChanCount;
    uint32_t        mInputFrameSize;
    uint32_t        mInputChunkFrames;
    uint32_t        mInputNominalLatencyUSec;
    LinearTransform mLocalTimeToFrames;

    // Bookkeeping used to throttle audio flinger when this audio stream has no
    // actual physical outputs.
    LocalClock      mLocalClock;
    bool            mThrottleValid;
    int64_t         mWriteStartLT;
    int64_t         mFramesWritten; // application rate frames, not device rate frames
    LinearTransform mUSecToLocalTime;

    // State to track which actual outputs are assigned to this output stream.
    Mutex           mRoutingLock; // This protects mPhysOutputs and mTgtDevices
    AudioOutputList mPhysOutputs;
    uint32_t        mTgtDevices;
    bool            mTgtDevicesDirty;
    uint32_t        mAudioFlingerTgtDevices;

    // Flag to track if this StreamOut was created to sink a direct output
    // multichannel stream.
    bool            mIsMCOutput;
    // Is the stream on standby?
    bool            mInStandby;
    // Is the stream compressed audio in SPDIF data bursts?
    const bool      mIsIec958NonAudio;

    // reduce log spew
    bool            mReportedAvailFail;

    status_t        standbyHardware();
    void            releaseAllOutputs(); // locks mRoutingLock
    void            updateTargetOutputs();  // locks mRoutingLock
    void            updateInputNums();
    void            finishedWriteOp(size_t framesWritten, bool needThrottle);
    void            resetThrottle() { mThrottleValid = false; }
    status_t        getNextWriteTimestamp_internal(int64_t *timestamp);
    void            adjustOutputs(int64_t maxTime);
    ssize_t         writeInternal(const void* buffer, size_t bytes);

    // mRoutingLock should be held before calling this.
    status_t        getPresentationPosition_l(uint64_t *frames, struct timespec *timestamp);
};

}  // android
#endif  // ANDROID_AUDIO_STREAM_OUT_H