summaryrefslogtreecommitdiffstats
path: root/dom/media/wave/WaveDemuxer.h
blob: 3424e1630f52b47958b7b9e20cbbc80f406eaffc (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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
/* This Source Code Form is subject to the terms of the Mozilla Public
 * Licence, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef WAV_DEMUXER_H_
#define WAV_DEMUXER_H_

#include "mozilla/Attributes.h"
#include "mozilla/Maybe.h"
#include "MediaDataDemuxer.h"
#include "MediaResource.h"
#include "mp4_demuxer/ByteReader.h"

using mp4_demuxer::ByteReader;

namespace mozilla {

static const uint32_t FRMT_CODE = 0x666d7420;
static const uint32_t DATA_CODE = 0x64617461;
static const uint32_t LIST_CODE = 0x4c495354;
static const uint32_t INFO_CODE = 0x494e464f;

static const uint8_t RIFF[4] = {'R', 'I', 'F', 'F'};
static const uint8_t WAVE[4] = {'W', 'A', 'V', 'E'};

static const uint16_t RIFF_CHUNK_SIZE = 12;
static const uint16_t CHUNK_HEAD_SIZE = 8;
static const uint16_t FMT_CHUNK_MIN_SIZE = 16;
static const uint16_t DATA_CHUNK_SIZE = 768;

class WAVTrackDemuxer;

class WAVDemuxer : public MediaDataDemuxer {
public:
  // MediaDataDemuxer interface.
  explicit WAVDemuxer(MediaResource* aSource);
  RefPtr<InitPromise> Init() override;
  bool HasTrackType(TrackInfo::TrackType aType) const override;
  uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override;
  already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer(
      TrackInfo::TrackType aType, uint32_t aTrackNumber) override;
  bool IsSeekable() const override;

private:
  // Synchronous Initialization.
  bool InitInternal();

  MediaResourceIndex mSource;
  RefPtr<WAVTrackDemuxer> mTrackDemuxer;
};

class RIFFParser {
private:
  class RIFFHeader;
public:
  const RIFFHeader& RiffHeader() const;

  uint32_t Parse(ByteReader& aReader);

  void Reset();

private:
  class RIFFHeader {
  public:
    RIFFHeader();
    void Reset();

    bool IsValid() const;
    bool IsValid(int aPos) const;

    bool ParseNext(uint8_t c);

  private:
    bool Update(uint8_t c);

    uint8_t mRaw[RIFF_CHUNK_SIZE];

    int mPos;
  };

  RIFFHeader mRiffHeader;
};

class HeaderParser {
private:
  class ChunkHeader;
public:
  const ChunkHeader& GiveHeader() const;

  uint32_t Parse(ByteReader& aReader);

  void Reset();

private:
  class ChunkHeader {
  public:
    ChunkHeader();
    void Reset();

    bool IsValid() const;

    uint32_t ChunkName() const;
    uint32_t ChunkSize() const;

    bool ParseNext(uint8_t c);

  private:
    void Update(uint8_t c);

    uint8_t mRaw[CHUNK_HEAD_SIZE];

    int mPos;
  };

  ChunkHeader mHeader;
};

class FormatParser {
private:
  class FormatChunk;
public:
  const FormatChunk& FmtChunk() const;

  uint32_t Parse(ByteReader& aReader);

  void Reset();

private:
  class FormatChunk {
  public:
    FormatChunk();
    void Reset();

    uint16_t WaveFormat() const;
    uint16_t Channels() const;
    uint32_t SampleRate() const;
    uint16_t FrameSize() const;
    uint16_t SampleFormat() const;

    bool IsValid() const;
    bool ParseNext(uint8_t c);

  private:
    void Update(uint8_t c);

    uint8_t mRaw[FMT_CHUNK_MIN_SIZE];

    int mPos;
  };

  FormatChunk mFmtChunk;
};

class DataParser {
private:
  class DataChunk;
public:
  DataParser();

  const DataChunk& CurrentChunk() const;

  void Reset();

private:
  class DataChunk {
  public:
    void Reset();
  private:
    int mPos; // To Check Alignment
  };

  DataChunk mChunk;
};

class WAVTrackDemuxer : public MediaTrackDemuxer {
public:
  explicit WAVTrackDemuxer(MediaResourceIndex aSource);

  bool Init();

  int64_t StreamLength() const;

  media::TimeUnit Duration() const;
  media::TimeUnit Duration(int64_t aNumDataChunks) const;
  media::TimeUnit DurationFromBytes(uint32_t aNumBytes) const;

  media::TimeUnit SeekPosition() const;

  RefPtr<MediaRawData> DemuxSample();

  // MediaTrackDemuxer interface.
  UniquePtr<TrackInfo> GetInfo() const override;
  RefPtr<SeekPromise> Seek(media::TimeUnit aTime) override;
  RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples) override;
  void Reset() override;
  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
    media::TimeUnit aTimeThreshold) override;
  int64_t GetResourceOffset() const override;
  media::TimeIntervals GetBuffered() override;

private:
  ~WAVTrackDemuxer() {}

  media::TimeUnit FastSeek(const media::TimeUnit& aTime);
  media::TimeUnit ScanUntil(const media::TimeUnit& aTime);

  MediaByteRange FindNextChunk();

  MediaByteRange FindChunkHeader();
  MediaByteRange FindRIFFHeader();
  MediaByteRange FindFmtChunk();
  MediaByteRange FindListChunk();
  MediaByteRange FindInfoTag();

  bool RIFFParserInit();
  bool HeaderParserInit();
  bool FmtChunkParserInit();
  bool ListChunkParserInit(uint32_t aChunkSize);

  bool SkipNextChunk(const MediaByteRange& aRange);

  already_AddRefed<MediaRawData> GetNextChunk(const MediaByteRange& aRange);
  already_AddRefed<MediaRawData> GetFileHeader(const MediaByteRange& aRange);

  void UpdateState(const MediaByteRange& aRange);

  int64_t OffsetFromChunkIndex(int64_t aChunkIndex) const;
  int64_t ChunkIndexFromOffset(int64_t aOffet) const;
  int64_t ChunkIndexFromTime(const media::TimeUnit& aTime) const;

  int32_t Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize);

  MediaResourceIndex mSource;

  DataParser mParser;
  RIFFParser mRIFFParser;
  HeaderParser mHeaderParser;

  FormatParser mFmtParser;
  // ListChunkParser mListChunkParser;

  int64_t mOffset;
  int64_t mFirstChunkOffset;

  uint32_t mNumParsedChunks;
  int32_t mChunkIndex;

  uint32_t mDataLength;
  uint64_t mTotalChunkLen;

  int32_t mSamplesPerChunk;
  int32_t mSamplesPerSecond;

  int32_t mChannels;
  int32_t mSampleFormat;

  UniquePtr<AudioInfo> mInfo;
};

} // namespace mozilla

#endif