diff options
Diffstat (limited to '')
-rw-r--r-- | dom/media/wave/WaveDemuxer.h | 266 |
1 files changed, 266 insertions, 0 deletions
diff --git a/dom/media/wave/WaveDemuxer.h b/dom/media/wave/WaveDemuxer.h new file mode 100644 index 0000000000..a7ab65c002 --- /dev/null +++ b/dom/media/wave/WaveDemuxer.h @@ -0,0 +1,266 @@ +/* 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 "MediaDataDemuxer.h" +#include "MediaResource.h" + +namespace mozilla { +class BufferReader; + +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; + +DDLoggedTypeDeclNameAndBase(WAVDemuxer, MediaDataDemuxer); +DDLoggedTypeNameAndBase(WAVTrackDemuxer, MediaTrackDemuxer); + +class WAVDemuxer : public MediaDataDemuxer, + public DecoderDoctorLifeLogger<WAVDemuxer> { + public: + // MediaDataDemuxer interface. + explicit WAVDemuxer(MediaResource* aSource); + RefPtr<InitPromise> Init() 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; + + Result<uint32_t, nsresult> Parse(BufferReader& 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; + + Result<uint32_t, nsresult> Parse(BufferReader& 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; + + Result<uint32_t, nsresult> Parse(BufferReader& 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 DecoderDoctorLifeLogger<WAVTrackDemuxer> { + public: + explicit WAVTrackDemuxer(MediaResource* 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(const media::TimeUnit& aTime) override; + RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples) override; + void Reset() override; + RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint( + const media::TimeUnit& aTimeThreshold) override; + int64_t GetResourceOffset() const override; + media::TimeIntervals GetBuffered() override; + + private: + ~WAVTrackDemuxer() = default; + + 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); + + uint64_t OffsetFromChunkIndex(uint32_t aChunkIndex) const; + uint64_t ChunkIndexFromTime(const media::TimeUnit& aTime) const; + + uint32_t Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize); + + MediaResourceIndex mSource; + + DataParser mParser; + RIFFParser mRIFFParser; + HeaderParser mHeaderParser; + + FormatParser mFmtParser; + // ListChunkParser mListChunkParser; + + uint64_t mOffset; + uint64_t mFirstChunkOffset; + + uint32_t mNumParsedChunks; + uint32_t mChunkIndex; + + uint32_t mDataLength; + uint64_t mTotalChunkLen; + + uint32_t mSamplesPerChunk; + uint32_t mSamplesPerSecond; + + uint32_t mChannels; + uint32_t mSampleFormat; + + UniquePtr<AudioInfo> mInfo; +}; + +} // namespace mozilla + +#endif |