summaryrefslogtreecommitdiffstats
path: root/dom/media/mp3/MP3Demuxer.h
blob: 5189e82acf8286fb25f4587d6350b2af88bced63 (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
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, 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 MP3_DEMUXER_H_
#define MP3_DEMUXER_H_

#include "MediaDataDemuxer.h"
#include "MediaResource.h"
#include "MP3FrameParser.h"

namespace mozilla {

class MP3TrackDemuxer;

DDLoggedTypeDeclNameAndBase(MP3Demuxer, MediaDataDemuxer);
DDLoggedTypeNameAndBase(MP3TrackDemuxer, MediaTrackDemuxer);

class MP3Demuxer : public MediaDataDemuxer,
                   public DecoderDoctorLifeLogger<MP3Demuxer> {
 public:
  // MediaDataDemuxer interface.
  explicit MP3Demuxer(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;
  void NotifyDataArrived() override;
  void NotifyDataRemoved() override;

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

  RefPtr<MediaResource> mSource;
  RefPtr<MP3TrackDemuxer> mTrackDemuxer;
};

// The MP3 demuxer used to extract MPEG frames and side information out of
// MPEG streams.
class MP3TrackDemuxer : public MediaTrackDemuxer,
                        public DecoderDoctorLifeLogger<MP3TrackDemuxer> {
 public:
  // Constructor, expecting a valid media resource.
  explicit MP3TrackDemuxer(MediaResource* aSource);

  // Initializes the track demuxer by reading the first frame for meta data.
  // Returns initialization success state.
  bool Init();

  // Returns the total stream length if known, -1 otherwise.
  int64_t StreamLength() const;

  // Returns the estimated stream duration, or a 0-duration if unknown.
  media::NullableTimeUnit Duration() const;

  // Returns the estimated duration up to the given frame number,
  // or a 0-duration if unknown.
  media::TimeUnit Duration(int64_t aNumFrames) const;

  // Returns the estimated current seek position time.
  media::TimeUnit SeekPosition() const;

  const FrameParser::Frame& LastFrame() const;
  RefPtr<MediaRawData> DemuxSample();

  const ID3Parser::ID3Header& ID3Header() const;
  const FrameParser::VBRHeader& VBRInfo() const;

  // MediaTrackDemuxer interface.
  UniquePtr<TrackInfo> GetInfo() const override;
  RefPtr<SeekPromise> Seek(const media::TimeUnit& aTime) override;
  RefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
  void Reset() override;
  RefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(
      const media::TimeUnit& aTimeThreshold) override;
  int64_t GetResourceOffset() const override;
  media::TimeIntervals GetBuffered() override;
  // Return the duration in frames of the encoder delay.
  uint32_t EncoderDelayFrames() const;
  // Return the duration  in frames of the padding.
  uint32_t PaddingFrames() const;

 private:
  // Destructor.
  ~MP3TrackDemuxer() = default;

  // Fast approximate seeking to given time.
  media::TimeUnit FastSeek(const media::TimeUnit& aTime);

  // Seeks by scanning the stream up to the given time for more accurate
  // results.
  media::TimeUnit ScanUntil(const media::TimeUnit& aTime);

  // Finds the first valid frame and returns its byte range if found
  // or a null-byte range otherwise.
  MediaByteRange FindFirstFrame();

  // Finds the next valid frame and returns its byte range if found
  // or a null-byte range otherwise.
  MediaByteRange FindNextFrame();

  // Skips the next frame given the provided byte range.
  bool SkipNextFrame(const MediaByteRange& aRange);

  // Returns the next MPEG frame, if available.
  already_AddRefed<MediaRawData> GetNextFrame(const MediaByteRange& aRange);

  // Updates post-read meta data.
  void UpdateState(const MediaByteRange& aRange);

  // Returns the estimated offset for the given frame index.
  int64_t OffsetFromFrameIndex(int64_t aFrameIndex) const;

  // Returns the estimated frame index for the given offset.
  int64_t FrameIndexFromOffset(int64_t aOffset) const;

  // Returns the estimated frame index for the given time.
  int64_t FrameIndexFromTime(const media::TimeUnit& aTime) const;

  // Reads aSize bytes into aBuffer from the source starting at aOffset.
  // Returns the actual size read.
  uint32_t Read(uint8_t* aBuffer, int64_t aOffset, uint32_t aSize);

  // Returns the average frame length derived from the previously parsed frames.
  double AverageFrameLength() const;

  // Returns the number of frames reported by the header if it's valid. Nothing
  // otherwise.
  Maybe<uint32_t> ValidNumAudioFrames() const;

  // Return the duration of the encoder delay.
  media::TimeUnit EncoderDelay() const;

  // Return the duration of the padding.
  media::TimeUnit Padding() const;

  // The (hopefully) MPEG resource.
  MediaResourceIndex mSource;

  // MPEG frame parser used to detect frames and extract side info.
  FrameParser mParser;

  // Whether we've locked onto a valid sequence of frames or not.
  bool mFrameLock;

  // Current byte offset in the source stream.
  int64_t mOffset;

  // Byte offset of the begin of the first frame, or 0 if none parsed yet.
  int64_t mFirstFrameOffset;

  // Total parsed frames.
  uint64_t mNumParsedFrames;

  // Current frame index.
  int64_t mFrameIndex;

  // Sum of parsed frames' lengths in bytes.
  int64_t mTotalFrameLen;

  // Samples per frame metric derived from frame headers or 0 if none available.
  uint32_t mSamplesPerFrame;

  // Samples per second metric derived from frame headers or 0 if none
  // available.
  uint32_t mSamplesPerSecond;

  // Channel count derived from frame headers or 0 if none available.
  uint32_t mChannels;

  // Audio track config info.
  UniquePtr<AudioInfo> mInfo;

  // Number of frames to skip at the beginning
  uint32_t mEncoderDelay = 0;
  // Number of frames to skip at the end
  uint32_t mEncoderPadding = 0;
  int32_t mRemainingEncoderPadding = 0;
  // End of stream has been found
  bool mEOS = false;
};

}  // namespace mozilla

#endif