summaryrefslogtreecommitdiffstats
path: root/dom/media/driftcontrol/AudioDriftCorrection.h
blob: aeb01d3d2bc55bafad5bb801b6b1ed35a805b029 (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
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
/* 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 DOM_MEDIA_DRIFTCONTROL_AUDIODRIFTCORRECTION_H_
#define DOM_MEDIA_DRIFTCONTROL_AUDIODRIFTCORRECTION_H_

#include "AudioSegment.h"
#include "TimeUnits.h"

namespace mozilla {

class AudioResampler;
class DriftController;

/**
 * Correct the drift between two independent clocks, the source, and the target
 * clock. The target clock is the master clock so the correction syncs the drift
 * of the source clock to the target. The nominal sampling rates of source and
 * target must be provided.
 *
 * It works with AudioSegment in order to be able to be used from the
 * MediaTrackGraph/MediaTrack. The audio buffers are pre-allocated so the only
 * new allocation taking place during operation happens if the input buffer
 * outgrows the memory allocated. The preallocation capacity is 100ms for input
 * and 100ms for output. The class consists of DriftController and
 * AudioResampler check there for more details.
 *
 * The class is not thread-safe. The construction can happen in any thread but
 * the member method must be used in a single thread that can be different than
 * the construction thread. Appropriate for being used in the high priority
 * audio thread.
 */
class AudioDriftCorrection final {
 public:
  AudioDriftCorrection(uint32_t aSourceRate, uint32_t aTargetRate,
                       const PrincipalHandle& aPrincipalHandle);

  ~AudioDriftCorrection();

  /**
   * A segment of input data (in the source rate) and a number of requested
   * output frames (in the target rate) are provided, and a segment (in the
   * target rate) of drift-corrected data is returned. The input is buffered
   * internally so some latency exists. The returned AudioSegment may not be
   * long-lived because any point in the internal buffer gets reused every
   * 100ms. If not enough data is available in the input buffer to produce
   * the requested number of output frames, the input buffer is drained and
   * a smaller segment than requested is returned.
   */
  AudioSegment RequestFrames(const AudioSegment& aInput,
                             uint32_t aOutputFrames);

  uint32_t CurrentBuffering() const;

  uint32_t BufferSize() const;

  uint32_t NumCorrectionChanges() const;

  uint32_t NumUnderruns() const { return mNumUnderruns; }

  void SetSourceLatency(media::TimeUnit aSourceLatency);

  const uint32_t mTargetRate;
  const media::TimeUnit mLatencyReductionTimeLimit =
      media::TimeUnit(15, 1).ToBase(mTargetRate);

 private:
  void SetDesiredBuffering(media::TimeUnit aDesiredBuffering);

  media::TimeUnit mSourceLatency = media::TimeUnit::Zero();
  media::TimeUnit mDesiredBuffering = media::TimeUnit::Zero();
  uint32_t mNumUnderruns = 0;
  bool mIsHandlingUnderrun = false;
  const UniquePtr<DriftController> mDriftController;
  const UniquePtr<AudioResampler> mResampler;
};
}  // namespace mozilla
#endif  // DOM_MEDIA_DRIFTCONTROL_AUDIODRIFTCORRECTION_H_