WaveDemuxer.h (5718B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * Licence, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef WAV_DEMUXER_H_ 6 #define WAV_DEMUXER_H_ 7 8 #include "MediaDataDemuxer.h" 9 #include "MediaResource.h" 10 11 namespace mozilla { 12 class BufferReader; 13 14 static const uint32_t FRMT_CODE = 0x666d7420; 15 static const uint32_t DATA_CODE = 0x64617461; 16 static const uint32_t LIST_CODE = 0x4c495354; 17 static const uint32_t INFO_CODE = 0x494e464f; 18 19 static const uint8_t RIFF[4] = {'R', 'I', 'F', 'F'}; 20 static const uint8_t WAVE[4] = {'W', 'A', 'V', 'E'}; 21 22 static const uint16_t RIFF_CHUNK_SIZE = 12; 23 static const uint16_t CHUNK_HEAD_SIZE = 8; 24 static const uint16_t FMT_CHUNK_MIN_SIZE = 16; 25 static const uint16_t DATA_CHUNK_SIZE = 768; 26 27 class WAVTrackDemuxer; 28 29 DDLoggedTypeDeclNameAndBase(WAVDemuxer, MediaDataDemuxer); 30 DDLoggedTypeNameAndBase(WAVTrackDemuxer, MediaTrackDemuxer); 31 32 class WAVDemuxer : public MediaDataDemuxer, 33 public DecoderDoctorLifeLogger<WAVDemuxer> { 34 public: 35 // MediaDataDemuxer interface. 36 explicit WAVDemuxer(MediaResource* aSource); 37 RefPtr<InitPromise> Init() override; 38 uint32_t GetNumberTracks(TrackInfo::TrackType aType) const override; 39 already_AddRefed<MediaTrackDemuxer> GetTrackDemuxer( 40 TrackInfo::TrackType aType, uint32_t aTrackNumber) override; 41 bool IsSeekable() const override; 42 43 private: 44 // Synchronous Initialization. 45 bool InitInternal(); 46 47 MediaResourceIndex mSource; 48 RefPtr<WAVTrackDemuxer> mTrackDemuxer; 49 }; 50 51 class RIFFParser { 52 private: 53 class RIFFHeader; 54 55 public: 56 const RIFFHeader& RiffHeader() const; 57 58 Result<uint32_t, nsresult> Parse(BufferReader& aReader); 59 60 void Reset(); 61 62 private: 63 class RIFFHeader { 64 public: 65 RIFFHeader(); 66 void Reset(); 67 68 bool IsValid() const; 69 bool IsValid(int aPos) const; 70 71 bool ParseNext(uint8_t c); 72 73 private: 74 bool Update(uint8_t c); 75 76 uint8_t mRaw[RIFF_CHUNK_SIZE] = {}; 77 78 int mPos = 0; 79 }; 80 81 RIFFHeader mRiffHeader; 82 }; 83 84 class HeaderParser { 85 private: 86 class ChunkHeader; 87 88 public: 89 const ChunkHeader& GiveHeader() const; 90 91 Result<uint32_t, nsresult> Parse(BufferReader& aReader); 92 93 void Reset(); 94 95 private: 96 class ChunkHeader { 97 public: 98 ChunkHeader(); 99 void Reset(); 100 101 bool IsValid() const; 102 103 uint32_t ChunkName() const; 104 uint32_t ChunkSize() const; 105 106 bool ParseNext(uint8_t c); 107 108 private: 109 void Update(uint8_t c); 110 111 uint8_t mRaw[CHUNK_HEAD_SIZE] = {}; 112 113 int mPos = 0; 114 }; 115 116 ChunkHeader mHeader; 117 }; 118 119 class FormatChunk { 120 public: 121 FormatChunk() = default; 122 void Init(nsTArray<uint8_t>&& aData); 123 124 uint16_t WaveFormat() const; 125 uint16_t Channels() const; 126 uint32_t SampleRate() const; 127 uint16_t ExtraFormatInfoSize() const; 128 uint16_t SampleFormat() const; 129 uint16_t AverageBytesPerSec() const; 130 uint16_t BlockAlign() const; 131 uint16_t ValidBitsPerSamples() const; 132 AudioConfig::ChannelLayout::ChannelMap ChannelMap() const; 133 134 private: 135 nsTArray<uint8_t> mRaw; 136 }; 137 138 class DataParser { 139 private: 140 class DataChunk; 141 142 public: 143 DataParser(); 144 145 const DataChunk& CurrentChunk() const; 146 147 void Reset(); 148 149 private: 150 class DataChunk { 151 public: 152 void Reset(); 153 154 private: 155 int mPos = 0; // To Check Alignment 156 }; 157 158 DataChunk mChunk; 159 }; 160 161 class WAVTrackDemuxer : public MediaTrackDemuxer, 162 public DecoderDoctorLifeLogger<WAVTrackDemuxer> { 163 public: 164 explicit WAVTrackDemuxer(MediaResource* aSource); 165 166 bool Init(); 167 168 int64_t StreamLength() const; 169 170 media::TimeUnit Duration() const; 171 media::TimeUnit Duration(int64_t aNumDataChunks) const; 172 media::TimeUnit DurationFromBytes(uint32_t aNumBytes) const; 173 174 media::TimeUnit SeekPosition() const; 175 176 RefPtr<MediaRawData> DemuxSample(); 177 178 // MediaTrackDemuxer interface. 179 UniquePtr<TrackInfo> GetInfo() const override; 180 RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override; 181 RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples) override; 182 void Reset() override; 183 RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint( 184 const media::TimeUnit& aTimeThreshold) override; 185 int64_t GetResourceOffset() const override; 186 media::TimeIntervals GetBuffered() override; 187 188 private: 189 ~WAVTrackDemuxer() = default; 190 191 media::TimeUnit FastSeek(const media::TimeUnit& aTime); 192 media::TimeUnit ScanUntil(const media::TimeUnit& aTime); 193 194 MediaByteRange FindNextChunk(); 195 196 MediaByteRange FindChunkHeader(); 197 MediaByteRange FindRIFFHeader(); 198 MediaByteRange FindFmtChunk(); 199 MediaByteRange FindListChunk(); 200 MediaByteRange FindInfoTag(); 201 202 bool RIFFParserInit(); 203 bool HeaderParserInit(); 204 bool FmtChunkParserInit(); 205 bool ListChunkParserInit(uint32_t aChunkSize); 206 207 bool SkipNextChunk(const MediaByteRange& aRange); 208 209 already_AddRefed<MediaRawData> GetNextChunk(const MediaByteRange& aRange); 210 already_AddRefed<MediaRawData> GetFileHeader(const MediaByteRange& aRange); 211 212 void UpdateState(const MediaByteRange& aRange); 213 214 uint64_t OffsetFromChunkIndex(uint32_t aChunkIndex) const; 215 uint64_t ChunkIndexFromTime(const media::TimeUnit& aTime) const; 216 217 int64_t Read(uint8_t* aBuffer, int64_t aOffset, int64_t aSize); 218 219 MediaResourceIndex mSource; 220 221 DataParser mParser; 222 RIFFParser mRIFFParser; 223 HeaderParser mHeaderParser; 224 225 FormatChunk mFmtChunk; 226 // ListChunkParser mListChunkParser; 227 228 uint64_t mOffset; 229 uint64_t mFirstChunkOffset; 230 231 uint32_t mNumParsedChunks; 232 uint32_t mChunkIndex; 233 234 uint32_t mDataLength; 235 uint64_t mTotalChunkLen; 236 237 uint32_t mSamplesPerChunk; 238 uint32_t mSamplesPerSecond; 239 240 uint32_t mChannels; 241 uint32_t mSampleFormat; 242 243 UniquePtr<AudioInfo> mInfo; 244 }; 245 246 } // namespace mozilla 247 248 #endif