summaryrefslogtreecommitdiffstats
path: root/audio_utils/include/audio_utils/spdif/FrameScanner.h
blob: f1f2cd1eab0a529d67c06295c2373487d88cede7 (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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/*
**
** Copyright 2014, 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_FRAME_SCANNER_H
#define ANDROID_AUDIO_FRAME_SCANNER_H

#include <stdint.h>

namespace android {


/**
 * Scan a byte stream looking for the start of an encoded frame.
 * Parse the sample rate and the size of the encoded frame.
 * Buffer the sync header so it can be prepended to the remaining data.
 *
 * This is used directly by the SPDIFEncoder. External clients will
 * generally not call this class.
 */
class FrameScanner {
public:

    FrameScanner(int dataType);
    virtual ~FrameScanner();

    /**
     * Pass each byte of the encoded stream to this scanner.
     * @return true if a complete and valid header was detected
     */
    virtual bool scan(uint8_t) = 0;

    /**
     * @return address of where the sync header was stored by scan()
     */
    virtual const uint8_t *getHeaderAddress() const = 0;

    /**
     * @return number of bytes in sync header stored by scan()
     */
    virtual size_t getHeaderSizeBytes() const = 0;

    /**
     * @return sample rate of the encoded audio
     */
    uint32_t getSampleRate()   const { return mSampleRate; }

    /**
     * Some formats, for example EAC3, are wrapped in data bursts that have
     * a sample rate that is a multiple of the encoded sample rate.
     * The default multiplier is 1.
     * @return sample rate multiplier for the SP/DIF PCM data bursts
     */
    uint32_t getRateMultiplier()   const { return mRateMultiplier; }

    size_t getFrameSizeBytes()     const { return mFrameSizeBytes; }

    /**
     * dataType is defined by the SPDIF standard for each format
     */
    virtual int getDataType()      const { return mDataType; }
    virtual int getDataTypeInfo()  const { return mDataTypeInfo; }

    /**
     * lengthCode is defined by the SPDIF standard
     * @return length of the frame in bits or bytes, depending on the format.
     */
    virtual int getLengthCode()  const = 0;
    virtual int getMaxChannels() const = 0;

    /**
     * @return the number of pcm frames that correspond to one encoded frame
     */
    virtual int getMaxSampleFramesPerSyncFrame() const = 0;
    virtual int getSampleFramesPerSyncFrame()    const = 0;

    /**
     * @return true if this parsed frame must be the first frame in a data burst.
     */
    virtual bool isFirstInBurst() = 0;

    /**
     * If this returns false then the previous frame may or may not be the last frame.
     * @return true if this parsed frame is definitely the last frame in a data burst.
     */
    virtual bool isLastInBurst()  = 0;

protected:
    uint32_t mSampleRate;
    uint32_t mRateMultiplier;
    size_t   mFrameSizeBytes;
    int      mDataType;
    int      mDataTypeInfo;
};

#define AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES          3
#define AC3_NUM_FRAME_SIZE_TABLE_ENTRIES          38
#define AC3_PCM_FRAMES_PER_BLOCK                 256
#define AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK        6
#define EAC3_RATE_MULTIPLIER                       4
#define EAC3_NUM_SAMPLE_RATE_TABLE_ENTRIES         3
#define EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES   38

class AC3FrameScanner : public FrameScanner
{
public:
    AC3FrameScanner();
    virtual ~AC3FrameScanner();

    virtual bool scan(uint8_t);

    virtual const uint8_t *getHeaderAddress() const { return mHeaderBuffer; }
    virtual size_t getHeaderSizeBytes() const { return sizeof(mHeaderBuffer); }

    virtual int getDataType()      const { return mDataType; }
    virtual int getDataTypeInfo()  const { return 0; }
    virtual int getLengthCode()    const { return mLengthCode; }
    virtual int getMaxChannels()   const { return 5 + 1; }

    virtual int getMaxSampleFramesPerSyncFrame() const { return EAC3_RATE_MULTIPLIER
            * AC3_MAX_BLOCKS_PER_SYNC_FRAME_BLOCK * AC3_PCM_FRAMES_PER_BLOCK; }
    virtual int getSampleFramesPerSyncFrame() const;

    virtual bool isFirstInBurst();
    virtual bool isLastInBurst();

protected:

    // Preamble state machine states.
    enum State {
         STATE_EXPECTING_SYNC_1,
         STATE_EXPECTING_SYNC_2,
         STATE_GATHERING,
         STATE_GOT_HEADER,
    };

    State parseHeader(void);

    State    mState;
    uint32_t mBytesSkipped;
    uint8_t  mHeaderBuffer[6];
    int      mLengthCode;
    int      mAudioBlocksPerSyncFrame;
    uint     mCursor;
    uint     mStreamType;
    uint     mSubstreamID;
    uint     mFormatDumpCount;

    static const uint8_t kAC3SyncByte1;
    static const uint8_t kAC3SyncByte2;
    static const uint16_t   kAC3SampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES];
    static const uint16_t kAC3FrameSizeTable[AC3_NUM_FRAME_SIZE_TABLE_ENTRIES]
            [AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES];

    static const uint16_t   kEAC3ReducedSampleRateTable[AC3_NUM_SAMPLE_RATE_TABLE_ENTRIES];
    static const uint16_t kEAC3BlocksPerFrameTable[EAC3_NUM_BLOCKS_PER_FRAME_TABLE_ENTRIES];

};

}  // namespace android
#endif  // ANDROID_AUDIO_FRAME_SCANNER_H